【问题标题】:Memory Allocated But Can't Be Freed C已分配但无法释放的内存 C
【发布时间】:2020-11-13 17:24:13
【问题描述】:

我目前正在用 C 编写一个项目,我的目标是创建一个字符串数组,并用文件中的单词填充它们(目前我只是显式插入一个字符串)。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(){
        
    int numLetters = 4;
    /* The Amount of words in each file, File 1, 2, 3 */
    int totalWordQuantity = 19829; 
    /*the word that we test, we add by two because first 4: word, 5th: \n, 6th: \0*/
    char word[numLetters + 1]; 
    /*how many times we've changed the character*/
    int letterSpot = 0; 
    /*the character that goes through the file*/
    char c; 
        
    char* wordDocuments[3] = {"WordDocuments/Two_Letter_Connections.txt", "WordDocuments/Three_Letter_Connections.txt", "WordDocuments/Four_Letter_Connections.txt"};
    /*Four Letter Word Document*/
    FILE *flwd = fopen(wordDocuments[numLetters - 2], "r"); 
    if(flwd == NULL){
        printf("Cold Dog.");
    } 
    /* P is a step ahead of c, because otherwise the words get super messed up. */
    char p = fgetc(flwd); 
    c = p; 
 
    /*This stores all of the words*/
    char** wordStorage = (char**)calloc(totalWordQuantity, sizeof(char*) * (numLetters + 1));
    int wordCount = 0; 
    int i;
    for(i = 0; i < totalWordQuantity; i++){
        wordStorage[i] = malloc(sizeof(char) * (numLetters + 1)); 
    }

    /* First, take the character */
    while((c = p) != EOF){
        p = fgetc(flwd);

        if((c == ' ' && p != '\n') || c == '\n'){
            strcpy(wordStorage[wordCount], "pies");  
            wordCount++;
        }
        c = p;
    }
    
    for(i = 0; i < totalWordQuantity; i++){
        free(wordStorage[i]); 
    }
    
    free(wordStorage);
    
    fclose(flwd); 
    return 0; 
}

这段代码没有收到任何编译问题,运行完美;但是,当我运行它时,valgrind 给了我这个错误:

==29== Memcheck, a memory error detector
==29== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==29== Command: ./flwp
==29==
==29== error calling PR_SET_PTRACER, vgdb might block
==29== Invalid write of size 4
==29==    at 0x109419: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==29==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==29==
==29==
==29== Process terminating with default action of signal 11 (SIGSEGV)
==29==  Access not within mapped region at address 0x0
==29==    at 0x109419: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==29==  If you believe this happened as a result of a stack
==29==  overflow in your program's main thread (unlikely but
==29==  possible), you can try to increase the size of the
==29==  main thread stack using the --main-stacksize= flag.
==29==  The main thread stack size used in this run was 8388608.
==29==
==29== HEAP SUMMARY:
==29==     in use at exit: 892,777 bytes in 19,831 blocks
==29==   total heap usage: 19,832 allocs, 1 frees, 896,873 bytes allocated
==29==
==29== LEAK SUMMARY:
==29==    definitely lost: 0 bytes in 0 blocks
==29==    indirectly lost: 0 bytes in 0 blocks
==29==      possibly lost: 0 bytes in 0 blocks
==29==    still reachable: 892,777 bytes in 19,831 blocks
==29==         suppressed: 0 bytes in 0 blocks
==29== Reachable blocks (those to which a pointer was found) are not shown.
==29== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==29==
==29== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==29==
==29== 1 errors in context 1 of 1:
==29== Invalid write of size 4
==29==    at 0x109419: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==29==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==29==
==29== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

博士。当我尝试运行它时内存崩溃。如果我将 while 循环和其中的所有行替换为:

for(int i = 0; i < totalWordQuantity; i++){
    strcpy(wordStorage[wordCount], "word"); 
}

任何帮助或改进问题的建议将不胜感激!谢谢!

【问题讨论】:

  • 访问非法内存位置可能会给您一种一切运行正常的印象,但仍然是未定义的行为。避免重新发明轮子,在 google 中进行简单搜索,您会发现如何从文件读取行到数组。试着看看他们在其他方面做了什么,并从你可能犯的错误中吸取教训。
  • 在分配指针数组时没有理由乘以numLetters + 1
  • fgetc() 的返回类型是int,而不是char。您需要使用 int 变量,以便正确地与 EOF 进行比较。
  • 我试图在分配指针数组时取出乘法,但这奇怪地给了我另一个问题。我还将 p & c 的类型更改为整数,但它没有修复内存泄漏。感谢您花时间帮助我解决此问题。这确实意味着很多。
  • 你能解释一下这个吗:FILE *flwd = fopen(wordDocuments[numLetters - 2], "r");

标签: c memory-leaks malloc dynamic-memory-allocation strcpy


【解决方案1】:

标题有点误导。该问题似乎不是内存泄漏,即已分配但从未释放的内存,而是非法内存访问。

也许问题只是因为路径不正确(因为您似乎使用的是 Cygwin 的 Valgrind),但由于错误处理不当,您无法看到它。

if(flwd == NULL){
    printf("Cold Dog.");
} 

尽管文件没有成功打开,但程序在此处继续执行。由于 stdout 被缓冲,在我的机器上我无法看到错误并获得 SEGFAULT。

if(flwd == NULL){
    fprintf( stderr, "Cold Dog.");
    exit(EXIT_FAILURE);
} 

还有一些其他问题:

char** wordStorage = (char**)calloc(totalWordQuantity, sizeof(char*) * (numLetters + 1));

您在此处分配了太多空间。您应该分配 totalWorldQuantity 乘以 sizeof char 指针 (char *)。

char** wordStorage = (char**)calloc(totalWordQuantity, sizeof(char*));

但这不应该导致除了过度分配之外的任何问题。

char p = fgetc(flwd); 

应该是

int p = fgetc(flwd); 

否则非 EOF 字符可能会被解释为 EOF。

【讨论】:

    猜你喜欢
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多