Tôi cố gắng tạo một luồng kết nối với cơ sở dữ liệu, lấy một số dữ liệu từ đó và in nó ra bảng điều khiển. Vấn đề là khi chủ đề này hoàn thành, nó sẽ đưa ra một ngoại lệ:
Nhân đôi miễn phí hoặc bị hỏng (ra)Hủy bỏ (kết xuất lõi)
Tôi đã thử sử dụng sqlite3 và pthread, nhưng hai người này không thực sự là bạn bè.
Tôi đoán vậy, nhưng tôi không chắc liệu vấn đề có xuất phát từ lớp cơ sở dữ liệu hay không.
Có ai biết điều gì đang tạo ra ngoại lệ không? Đây là mã của tôi:liên kết
Lớp cơ sở dữ liệu:
Cơ sở dữ liệu lớp {
private:
sqlite3 *db;
int tĩnh CallBack(void *data, int argc, char **argv, char **azColName)
{
chỉ số int = 0;
char** dataToReturn = char mới*[1000];
trong khi (dataToReturn[chỉ mục])
{
chỉ mục++;
}
cho (int i = chỉ mục; i < argc + chỉ mục; i++)
{
dataToReturn[i] = (char *)malloc(sizeof(char) * sizeof(argv[i - index]));
strcpy((dataToReturn)[i], argv[i - index]);
}
return 0;
}
public:
char **Chọn()
{
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("test.db", &db);
nếu(rc)
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(1);
}
khác
{
fprintf(stderr, "Đã mở cơ sở dữ liệu thành công\n");
}
dữ liệu char **;
int rc2 = sqlite3_exec(db, "CHỌN * TỪ SHARED_FILE", Gọi lại, dữ liệu, &zErrMsg);
nếu (rc2 != SQLITE_OK)
{
sqlite3_free(zErrMsg);
exit(2);
}
sqlite3_close(db);
trả về dữ liệu;
}
Chức năng chủ đề:
khoảng trống tĩnh FuncioForThread()
{
printf("bắt đầu");
cơ sở dữ liệu tự động = Cơ sở dữ liệu mới();
char** returnData = cơ sở dữ liệu->Chọn();
printf("thứ gì đó từ db: %s \n", returnData[0]);
printf("dừng");
}
khoảng trống tĩnh *threadd(void *arg)
{
pthread_detach(pthread_self());
fflush(stdout);
FuncioForThread();
}
Chức năng chính:
int main()
{
chủ đề pthread_t;
char arg[100] = "kiểm tra";
pthread_create(&thread, NULL, &threadd, arg);
trong khi(1);
}
Bạn đang hủy tham chiếu((char **)dữ liệu)[chỉ mục]
được chuyển đếnGọi lại
củadata
, nhưng giá trị của nó được chuyểnsqlite3_exec
Cuộc gọi lại từSelect
TRONGdata
được truyền lại. Select
TRONG data
Đã được giao cho:
char **data = (char **)malloc(0);
Không được phép tham chiếu con trỏ được phân bổ có độ dài bằng 0. Cũng lưu ý rằng kích thước bằng không malloc
Hành vi của được xác định theo cách triển khai, do đó nên tránh (giống như trong C++ malloc
trong mọi trường hợp được ưu tiên hơn new
Như nhau).
Sau khi chỉnh sửa:
Hiện nay data
từ Select
được trả lại, nhưng không bao giờ được viết vào nó, nhưng sau đó trong
Dereference trong
returnData[0]
hiện hữuChức năngForThread
ở giữa. Đây là hành vi không xác định.
此外,sizeof(argv[i - chỉ mục])
sẽ không trở lại argv[i - chỉ mục]
Độ dài của chuỗi được chỉ tới. Nó sẽ trả về kích thước của kiểu con trỏ. Do đó, phân bổ của bạn có thể quá nhỏ, lại là hành vi không xác định. sử dụng std::stlen
Lấy độ dài của chuỗi kết thúc bằng 0.
Sau đó con trỏargv[i - chỉ mục]
Nó cũng có thể làNULL
để chỉ ra hàng trở lạiNULL
giá trị (xemtài liệu của sqlite3_exec
). Trong trường hợp này tiến hành từ strcpy
Hoạt động cũng sẽ là hành vi không xác định.
循环trong khi (dataToReturn[chỉ mục])
sẽ dẫn đến hành vi không xác định vìdữ liệuToReturn
Mảng được phân bổ nhưng các phần tử của nó không bao giờ được đặt. Ngay cả khi giá trị được đặt, hãy lưu ý rằng chuỗi kiểu C khi và chỉ khi dữ liệuToReturn[chỉ mục]
Điều kiện chỉ được đáp ứng khi chiều dài nhọn bằng 0. Nếu không có chuỗi nào tồn tại trong phạm vi được phân bổ thì hành vi đó lại không được xác định.
Bạn cũng bị rò rỉ bộ nhớ vì bạn không bao giờgiải phóng
bất kìmalloc
dữ liệu và bởi vìdữ liệuToReturn
bị loại bỏ vào cuối mỗi cuộc gọi CallBack, vì vậy nó không hữu ích lắm.
Không có lý do chính đáng nào để sử dụng tất cả các cấu trúc kiểu C này. sử dụng new
thay thế malloc
,sử dụng std::chuỗi
Và std::vector
thay thế ký tự
Mảng, sử dụng std::cout
Và std::cerr
thay thế printf
Và fprintf(stcerr, ...
,std::chủ đề
thay thế pthread
. Điểm duy nhất cần xem xét là ranh giới giao diện của thư viện C.
Tôi là một lập trình viên xuất sắc, rất giỏi!