2010-06-07 53 views
54

Tôi đang triển khai thuật toán đa thức và phân chia để đánh bại, vì vậy tôi có thể đánh giá nó so với triển khai OpenCL, nhưng tôi không thể nhận được malloc để hoạt động. Khi tôi chạy chương trình, nó phân bổ một loạt các công cụ, kiểm tra một số thứ, sau đó gửi size/2 đến thuật toán. Sau đó, khi tôi nhấn dòng malloc một lần nữa nó spits ra này:Tại sao tôi nhận được xác nhận của lệnh malloc C?

malloc.c: 3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) & ((av) - > thùng [((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) & & old_size == 0) || ((unsigned long) (old_size)> = (unsigned long) ((((__ builtin_offsetof (struct malloc_chunk, fd_nextsize)) + ((2 * (sizeof (size_t))) - 1)) & ~ ((2 * (sizeof (size_t))) - 1))) & & ((old_top) -> kích thước & 0x1) & & ((chưa ký dài) old_end & pagemask) == 0) 'không thành công. Aborted

Các dòng trong câu hỏi là:

int *mult(int size, int *a, int *b) { 
    int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2; 
    fprintf(stdout, "size: %d\n", size); 

    out = (int *)malloc(sizeof(int) * size * 2); 
} 

Tôi đã kiểm tra kích thước với một fprintf, và nó là một số nguyên dương (thường là 50 vào thời điểm đó). Tôi đã thử gọi số malloc với số đơn giản và tôi vẫn gặp lỗi. Tôi chỉ bối rối với những gì đang xảy ra, và không có gì từ Google tôi đã tìm thấy cho đến nay là hữu ích.

Bất kỳ ý tưởng gì đang xảy ra? Tôi đang cố gắng tìm ra cách để biên dịch một GCC mới hơn trong trường hợp đó là một lỗi trình biên dịch, nhưng tôi thực sự nghi ngờ nó.

+0

tôi nghi ngờ vấn đề thực sự là một dòng trước đó. Có lẽ một đôi miễn phí? –

+0

dòng thứ 3 trong chương trình: int * mult (kích thước int, int * a, int * b) { \t int * ra, i, j, * tmp1, * tmp2, * tmp3, * tmpa1 , * tmpa2, * tmpb1, * tmpb2, d, * res1, * res2; \t fprintf (stdout, "size:% d \ n", size); \t \t out = (int *) malloc (sizeof (int) * size * 2); – Chris

Trả lời

65

99,9% khả năng là bạn đã bị hỏng bộ nhớ (quá mức hoặc dưới chảy một bộ đệm, đã viết thư cho một con trỏ sau khi được trả tự do, được gọi miễn phí hai lần trên cùng một con trỏ, vv)

Chạy mã của bạn dưới Valgrind để xem nơi chương trình của bạn đã làm điều gì đó không chính xác.

+1

cố định. Valgrind chắc chắn đã giúp. Tôi sao chép mã MATLAB cũ của tôi sai và đã có một vòng lặp lặp đi lặp lại trên j, sau đó bên trong nó đã làm j + + mà hầu hết ghi đè lên mảng nó đã được viết trên và bằng cách nào đó gây ra malloc thất bại. cảm ơn sự giúp đỡ! – Chris

+0

Valgrind chỉ là công cụ tôi cần để tìm ra những gì đang xảy ra khi tôi gặp lỗi này. Cảm ơn bạn đã đề cập đến nó. – alexwells

+1

Tôi đã xây dựng sạch sẽ và nó hoạt động chính xác. –

2

Có thể bạn đã vượt quá mức mem được phân bổ ở đâu đó. sau đó sw cơ bản không nhận trên nó cho đến khi bạn gọi malloc

Có thể có một giá trị bảo vệ clobbered đang bị bắt bởi malloc.

chỉnh sửa ... thêm này cho kiểm tra giới hạn giúp

http://www.lrde.epita.fr/~akim/ccmp/doc/bounds-checking.html

1

Chúng tôi đã nhận lỗi này bởi vì chúng tôi đã quên nhân với sizeof (int). Lưu ý đối số cho malloc (..) là một số byte, không phải số lượng từ máy hoặc bất kỳ từ nào.

0

Tôi đã porting một ứng dụng từ Visual C để gcc trên Linux và tôi đã có cùng một vấn đề với

malloc.c: 3096: sYSMALLOc: Khẳng định sử dụng gcc trên Ubuntu 11.

Tôi đã chuyển mã giống nhau sang bản phân phối Suse (trên máy tính khác) và tôi không gặp bất kỳ vấn đề gì.

Tôi nghi ngờ rằng các vấn đề không có trong chương trình của chúng tôi nhưng trong libc của chính nó.

40

Để giúp bạn hiểu rõ hơn về lý do tại sao điều này xảy ra, tôi muốn mở rộng câu trả lời của @ r-samuel-klatchko một chút.

Khi bạn gọi malloc, điều thực sự xảy ra phức tạp hơn một chút so với việc chỉ cho bạn một đoạn bộ nhớ để chơi cùng. Dưới mui xe, malloc cũng giữ một số thông tin vệ sinh về bộ nhớ mà nó cung cấp cho bạn (quan trọng nhất là kích thước của nó), để khi bạn gọi free, nó biết những thứ như bao nhiêu bộ nhớ miễn phí. Thông tin này thường được lưu giữ ngay trước khi vị trí bộ nhớ được trả lại cho bạn bởi malloc. Xem thêm thông tin đầy đủ có thể được tìm thấy on the internet™, nhưng (rất) Ý tưởng cơ bản là một cái gì đó như thế này:

+------+-------------------------------------------------+ 
+ size |     malloc'd memory    + 
+------+-------------------------------------------------+ 
     ^-- location in pointer returned by malloc 

Xây dựng về vấn đề này (và đơn giản hóa mọi thứ rất nhiều), khi bạn gọi malloc, nó cần phải có được một con trỏ đến phần tiếp theo của bộ nhớ có sẵn. Một cách rất đơn giản để làm điều này là nhìn vào bit trước của bộ nhớ nó đã cho đi, và di chuyển thêm size byte xuống (hoặc lên) trong bộ nhớ. Với việc thực hiện này, bạn kết thúc với bộ nhớ bạn đang tìm kiếm một cái gì đó như thế này sau khi phân bổ p1, p2p3:

+------+----------------+------+--------------------+------+----------+ 
+ size |    | size |     | size |   + 
+------+----------------+------+--------------------+------+----------+ 
     ^- p1     ^- p2      ^- p3 

Vì vậy, những gì đang gây ra lỗi lầm của mình? Vâng, hãy tưởng tượng rằng mã của bạn ghi sai số lượng bộ nhớ bạn đã phân bổ (hoặc do bạn phân bổ ít hơn mức cần thiết vì vấn đề của bạn hoặc vì bạn đang sử dụng sai điều kiện ranh giới ở đâu đó trong mã của mình). Giả sử mã của bạn viết rất nhiều dữ liệu đến p2 mà nó bắt đầu ghi đè lên những gì trong trường size của p3. Khi bạn bây giờ tiếp theo gọi malloc, nó sẽ xem xét vị trí bộ nhớ cuối cùng nó quay trở lại, nhìn vào trường kích thước của nó, di chuyển đến p3 + size và sau đó bắt đầu phân bổ bộ nhớ từ đó. Vì mã của bạn đã ghi đè lên size, tuy nhiên, vị trí bộ nhớ này không còn sau bộ nhớ được cấp phát trước đó nữa.

Không cần phải nói, điều này có thể phá hoại sự tàn phá! Do đó, những người triển khai malloc đã đưa vào một số "xác nhận" hoặc kiểm tra, cố gắng thực hiện một loạt kiểm tra sanity để nắm bắt vấn đề này (và các vấn đề khác) nếu chúng sắp xảy ra. Trong trường hợp cụ thể của bạn, các xác nhận này bị vi phạm và do đó, malloc hủy bỏ, cho bạn biết rằng mã của bạn sắp sửa thực hiện điều gì đó mà bạn thực sự không nên làm.

Như đã nêu trước đây, đây là tổng quá trình đơn giản hóa, nhưng đủ để minh họa điểm. Việc triển khai glibc của malloc là hơn 5k dòng, và đã có một số lượng đáng kể nghiên cứu về cách xây dựng các cơ chế cấp phát bộ nhớ động tốt, do đó, bao gồm tất cả trong một câu trả lời SO là không thể. Hy vọng rằng điều này đã cho bạn một chút về một cái nhìn của những gì thực sự gây ra vấn đề mặc dù!

+0

Đây phải là câu trả lời được chấp nhận .. –

1

tôi đã được thông báo sau, tương tự như một của bạn:

 

    program: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed. 

Made một sai lầm một số phương pháp gọi trước đây, khi sử dụng malloc. Viết sai ký tự '*' bằng dấu '+', khi cập nhật hệ số sau toán tử sizeof() - thêm một trường vào mảng char chưa ký.

Đây là mã chịu trách nhiệm về sai sót trong trường hợp của tôi:

 

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)+5); 
    b[INTBITS]=(some calculation); 
    b[BUFSPC]=(some calculation); 
    b[BUFOVR]=(some calculation); 
    b[BUFMEM]=(some calculation); 
    b[MATCHBITS]=(some calculation); 

Trong phương pháp khác sau này, tôi sử dụng malloc một lần nữa và nó được sản xuất thông báo lỗi hiển thị ở trên. Cuộc gọi được (đơn giản đủ):

 

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)*50); 

suy nghĩ bằng cách sử dụng '+' - dấu hiệu về cuộc gọi 1st, dẫn đến mis-calculus kết hợp với khởi tạo trực tiếp của mảng sau (ghi đè lên bộ nhớ đó không phải là được phân bổ cho mảng), đưa một số nhầm lẫn vào bản đồ bộ nhớ của malloc. Vì vậy, cuộc gọi thứ 2 đã bị lỗi.

0

tôi gặp vấn đề tương tự, tôi đã sử dụng malloc trên n lần nữa trong vòng lặp để thêm dữ liệu chuỗi char * mới. tôi phải đối mặt với cùng một vấn đề, nhưng sau khi phát hành bộ nhớ phân bổ void free() vấn đề đã được sắp xếp

Các vấn đề liên quan