У меня возникла бешеная проблема, когда я зависал на malloc
/ calloc
/ strdup
, и в настоящее время я предполагаю, что это из-за переполнения буфера.
Мне очень трудно это найти, и мне было интересно, кто-нибудь из вас может предложить мне руку. Я выложу здесь фрагменты кода и ссылку на полный исходный код.
Чтение файлов и операции с массивами: (common.c)
Pastebin
char * S6_ReadFileBytes(const char* path)
FILE * file;
long length;
char * bytes = NULL;
file = fopen(path, "r");
fseek(file, 0, SEEK_END)
length = ftell(file);
fseek(file, 0, 0);
bytes = (char*)calloc(1, (size_t)length + 1);
fread(bytes, 1, (size_t)length, file);
return bytes;
S6_Array * S6_ArrayNew(size_t count, size_t typeSize)
S6_Array * a = (S6_Array*)malloc(sizeof(S6_Array));
a->typeSize = typeSize;
a->Length = count;
void * S6_ArrayGet(S6_Array * a, int idx)
return &((char*)a->Data)[idx * a->typeSize];
void S6_ArraySet(S6_Array * a, int idx, void * val)
memcpy(&((char*)a->Data)[idx * a->typeSize], val, a->typeSize);
void S6_ArrayGrow(S6_Array * a, int amount)
void * data;
data = realloc(a->Data, (a->Length + amount) * a->typeSize);
a->Data = data;
a->Length += amount;
void S6_ArrayPushBack(S6_Array * a, void* val)
S6_ArrayGrow(a, 1);
S6_ArraySet(a, a->Length - 1, val);
Чтение CSV: (CSV.c)
Pastebin
void S6_CSV_PushRect(S6_Array ** rectangles, S6_Rectangle * rect)
if( !*rectangles )
*rectangles = S6_ArrayNew(1, sizeof(S6_Rectangle*));
S6_ArraySet(*rectangles, 0, &rect);
else
S6_ArrayPushBack(*rectangles, &rect);
int S6_CSV_ReadRects(const char* file, S6_Array ** rectangles)
char * bytes = S6_ReadFileBytes(file);
char * line;
char * nameIndex;
size_t nameLength;
S6_Rectangle * tempRect;
line = strtok( bytes , "\n");
while( line )
nameIndex = strstr(line, ",");
tempRect = (S6_Rectangle*)calloc(1, sizeof(S6_Rectangle));
nameLength = (size_t)(nameIndex - line) + 1;
strncpy(tempRect->name, line, nameLength-1);
tempRect->name[nameLength-1] = '\0';
sscanf(nameIndex, "%*[,]%d%*[,]%d%*[,]%d%*[,]%d", &tempRect->x, &tempRect->y, &tempRect->w, &tempRect->h)
S6_CSV_PushRect(rectangles , tempRect);
strtok(NULL, "\n");
free(bytes);
Функция, в которой я изменяю массив: (BinPacker.c)
Pastebin
int S6_BinPacker_Pack(S6_Array * rectangles, int binSize)
// This sort appears to be working fine. View pastebin for test.
qsort(rectangles->Data, rectangles->Length, sizeof(S6_Rectangle*), S6_BinPacker_CompareRects);
CSV Writing [CRASH]
: (CSV.c)
Pastebin
void S6_CSV_WriteRects(const char* file, S6_Array * rectangles)
char * bytes = NULL;
char buffer[128];
S6_Rectangle * tempRect;
size_t i;
for( i = 0; i < rectangles->Length; ++i)
tempRect = *(S6_Rectangle**)S6_ArrayGet(rectangles, i);
memset(buffer, '\0', sizeof(buffer));
sprintf(buffer,
"%s,%d,%d,%d,%d\n",
tempRect->name,
temprect->x,
temprect->y,
temprect->w,
temprect->h);
if( bytes )
bytes = strcat(bytes, _strdup(buffer));
else
bytes = _strdup(buffer);
Итак, я рушусь здесь, на линии strcat(bytes, _strdup(buffer))
. Когда я выделяю его, это все еще дублирование строк или любое другое распределение, которое я пробовал.
Я получаю следующий диалог от Visual Studio:
Windows has triggered a breakpoint in myapp.exe.
This may be due to a corruption of the heap, which indicates a bug in Slant6.Debug.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while Slant6.Debug.exe has focus.
The output window may have more diagnostic information.
И точка прерывания, которую он вызывает, находится в tidtable.c на
PFLS_GETVALUE_FUNCTION flsGetValue = FLS_GETVALUE;
РЕШЕНИЕ
strdup не делает никаких распределений, и даже если бы это было так, я бы протекал как сумасшедший. Так что вместо:
bytes = strcat(bytes, _strdup(buffer));
в CSV.c я заменил его на ручную конкатенацию строк, которую мне легче читать (и помнить).
size_t oldSize = strlen(bytes);
size_t bufferSize = strlen(buffer);
size_t newSize = oldSize + bufferSize ;
char * newMem = (char*)calloc(newSize + 1, 1);
memcpy(newMem, bytes, newSize);
memcpy(&newMem[oldSize], buffer, bufferSize);
free(bytes);
bytes = newMem;
/ РЕШЕНИЕ