使用C语言qsort排序结构体时触发Address Boundary Error的排查及相关问题咨询
Hey there, let's break down the issues causing your Address Boundary Error and other related problems step by step.
qsort Call (Primary Cause of Address Boundary Error) Your qsort invocation has a critical mistake in the third parameter:
qsort(nodeList, num_id, sizeof(nodeList),cmp);
sizeof(nodeList) returns the size of the pointer itself (8 bytes on 64-bit systems), but qsort requires the size of a single data_id struct. This error makes qsort calculate element offsets incorrectly, leading to out-of-bounds memory access and the Address Boundary Error you're seeing.
Fix it by passing the correct element size:
qsort(nodeList, num_id, sizeof(data_id), cmp);
Your current comparison logic compares pointer addresses instead of string content, and it doesn't handle NULL id values:
if (v1->id < v2->id) return -1; else if (v1->id > v2->id) return +1;
This compares where the id strings are stored in memory, not their actual content. Worse, if any id is NULL, this will cause undefined behavior (and likely crashes).
Use strcmp for string comparison and add NULL handling:
int cmp(const void *p1, const void *p2) { const data_id *v1 = (const data_id *)p1; const data_id *v2 = (const data_id *)p2; // Handle NULL IDs first (adjust ordering as needed) if (v1->id == NULL && v2->id == NULL) return 0; if (v1->id == NULL) return -1; // Place NULLs at the start if (v2->id == NULL) return 1; // Compare actual string content return strcmp(v1->id, v2->id); }
create_list Your array management has multiple red flags:
- Fixed-size allocation: You only call
realloconce for 10000 elements. If your input has more entries, accessingnodeList[num_id]will go out of bounds. Implement dynamic resizing: check ifnum_idreaches the current capacity, then double the array size withrealloc. - Index confusion: The
tmp_idandnum_idvariables are being incremented and used interchangeably, leading to ambiguous accesses (e.g., writing tonodeList[tmp_id]andnodeList[num_id]which point to the same index after incrementing). Stick tonum_idas the count of valid elements, and add new entries tonodeList[num_id]before incrementing it. - Unchecked allocations:
reallocandcalloccan return NULL on failure. Always check their return values to avoid accessing NULL pointers.
Your stop_flag isn't fully preventing new entries because it doesn't immediately halt processing once set. Add a guard at the start of create_list to skip all logic when the flag is active:
void create_list(int input){ // Note: Explicitly declare input type! if (stop_flag) return; // Skip all processing once stopped // ... rest of your code }
This ensures no new entries are added after the 'A' line is processed.
After sorting, iterate through the array to filter out entries with NULL id values. Don't forget to free memory for discarded entries to avoid leaks:
// After qsort completes int valid_count = 0; for (int i = 0; i < num_id; i++) { if (nodeList[i].id != NULL) { if (i != valid_count) { nodeList[valid_count] = nodeList[i]; } valid_count++; } else { free(nodeList[i].id); // Clean up unused string memory } } num_id = valid_count; // Optional: Shrink the array to match valid count nodeList = realloc(nodeList, sizeof(data_id) * num_id);
strconcatNULL safety: IfnodeList[num_id].idis NULL when callingstrconcat(2, nodeList[num_id].id, buffer),strlen(NULL)will cause a crash. Add checks instrconcatfor NULL parameters, or ensureidis always initialized before concatenation.- Memory leak cleanup: Make sure to free all
idpointers allocated bystrconcatwhen the array is no longer needed (e.g., at program exit). - Duplicate entry handling: To de-duplicate nodes, after sorting, iterate through the array and remove adjacent entries with matching
idvalues (usestrcmpto compare).
内容的提问来源于stack exchange,提问作者Cina

