while循环出现Segmentation fault,Valgrind未检测到错误求排查
Fixing Segmentation Fault in Dynamic Memory Word Parser
Hey there, let's dig into that segmentation fault you're hitting with your dynamic memory word-parsing code. Segfaults here almost always boil down to uninitialized pointers, out-of-bounds memory writes, or missing checks for failed memory allocations. Let's break down the common issues in your approach and fix them step by step.
Common Causes of Your Segfault
From the code snippet you shared, these are the most likely culprits:
- Uninitialized pointers: If
wordorwordListaren't properly initialized toNULLbefore allocation, you might be accessing garbage memory. - No memory allocation failure checks:
malloc/realloccan returnNULLif memory is exhausted—using that null pointer will trigger a segfault. - Missing dynamic expansion: If your input has longer words than
WFactoror more words thanWLFactor, you'll write beyond the allocated memory bounds. - Unterminated strings: Without adding a
'\0'to the end of eachword, any string operation (like copying it towordList) will read past the valid memory.
Fixed Code with Explanations
Here's a complete, working version of your parser that addresses all these issues, with comments explaining key fixes:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char* word = NULL; int WFactor = 30; int WLFactor = 30; char** wordList = NULL; int wordCount = 0; int letterCount = 0; // Initialize word memory with error checking word = malloc(WFactor * sizeof(char)); if (word == NULL) { perror("Failed to allocate memory for word"); return 1; } // Initialize wordList memory with error checking wordList = malloc(WLFactor * sizeof(char*)); if (wordList == NULL) { perror("Failed to allocate memory for wordList"); free(word); // Clean up already allocated memory before exiting return 1; } char c; // Read input character by character until EOF while ((c = getchar()) != EOF) { if (c == ' ' || c == '\n') { // Handle spaces and newlines as word separators if (letterCount > 0) { // Skip empty "words" from consecutive spaces // Terminate the current word to make it a valid C string word[letterCount] = '\0'; // Expand wordList if we've hit its capacity if (wordCount >= WLFactor) { WLFactor *= 2; // Double capacity (common efficient strategy) char** tempList = realloc(wordList, WLFactor * sizeof(char*)); if (tempList == NULL) { perror("Failed to expand wordList"); // Clean up all allocated memory before exiting for (int i = 0; i < wordCount; i++) { free(wordList[i]); } free(wordList); free(word); return 1; } wordList = tempList; } // Allocate memory for the word copy in wordList wordList[wordCount] = malloc((letterCount + 1) * sizeof(char)); if (wordList[wordCount] == NULL) { perror("Failed to allocate memory for word entry"); // Clean up to avoid leaks for (int i = 0; i < wordCount; i++) { free(wordList[i]); } free(wordList); free(word); return 1; } strcpy(wordList[wordCount], word); wordCount++; // Reset for next word letterCount = 0; } } else { // Expand word if we're running out of space (leave room for '\0') if (letterCount >= WFactor - 1) { WFactor *= 2; char* tempWord = realloc(word, WFactor * sizeof(char)); if (tempWord == NULL) { perror("Failed to expand word"); // Clean up for (int i = 0; i < wordCount; i++) { free(wordList[i]); } free(wordList); free(word); return 1; } word = tempWord; } word[letterCount] = c; letterCount++; } } // Handle the final word if input doesn't end with a space/newline if (letterCount > 0) { word[letterCount] = '\0'; // Check wordList capacity again if (wordCount >= WLFactor) { WLFactor *= 2; char** tempList = realloc(wordList, WLFactor * sizeof(char*)); if (tempList == NULL) { perror("Failed to expand wordList for final word"); for (int i = 0; i < wordCount; i++) { free(wordList[i]); } free(wordList); free(word); return 1; } wordList = tempList; } wordList[wordCount] = malloc((letterCount + 1) * sizeof(char)); if (wordList[wordCount] == NULL) { perror("Failed to allocate memory for final word"); for (int i = 0; i < wordCount; i++) { free(wordList[i]); } free(wordList); free(word); return 1; } strcpy(wordList[wordCount], word); wordCount++; } // Test output to verify parsing printf("Parsed %d words:\n", wordCount); for (int i = 0; i < wordCount; i++) { printf("%d: %s\n", i+1, wordList[i]); } // Clean up all dynamically allocated memory free(word); for (int i = 0; i < wordCount; i++) { free(wordList[i]); } free(wordList); return 0; }
Key Fixes Explained
- Pointer Initialization:
wordandwordListstart asNULLto avoid accessing uninitialized memory. - Error Checking: Every
malloc/realloccall is checked forNULLreturns, with proper cleanup of already allocated memory before exiting. - Dynamic Expansion: Both
word(for long words) andwordList(for many words) are expanded when they reach capacity usingrealloc. - String Termination: Each word gets a
'\0'added before being stored inwordList, ensuring valid string operations. - Final Word Handling: The loop doesn't miss the last word if the input ends with a character instead of a space.
- Memory Cleanup: All allocated memory is freed before the program exits to avoid leaks.
内容的提问来源于stack exchange,提问作者jamespatel101
相关产品推荐
相关产品推荐

