Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C:动态字符数组崩溃堆_C_Char_Malloc_Heap_Realloc - Fatal编程技术网

C:动态字符数组崩溃堆

C:动态字符数组崩溃堆,c,char,malloc,heap,realloc,C,Char,Malloc,Heap,Realloc,我还有一个关于C语言工作原理的问题。(VS2012编译的ANSI-C) 我正在将独立程序(.exe)重构为.dll。到目前为止,这一切都很好,但当涉及到日志记录时,我遇到了一些问题。让我解释一下: 原始程序在运行时编写了一个日志文件并将信息打印到屏幕上。由于我的dll将在Web服务器上运行,许多人同时访问,因此 没有真正的机会正确处理日志文件(并在日志文件之后进行清理) 没有任何人会看到控制台窗口 因此,我的目标是将日志文件或屏幕上的所有内容写入类似字符串的变量(我知道C中没有字符串),然后

我还有一个关于C语言工作原理的问题。(VS2012编译的ANSI-C)

我正在将独立程序(.exe)重构为.dll。到目前为止,这一切都很好,但当涉及到日志记录时,我遇到了一些问题。让我解释一下:

原始程序在运行时编写了一个日志文件并将信息打印到屏幕上。由于我的dll将在Web服务器上运行,许多人同时访问,因此

  • 没有真正的机会正确处理日志文件(并在日志文件之后进行清理)
  • 没有任何人会看到控制台窗口
因此,我的目标是将日志文件或屏幕上的所有内容写入类似字符串的变量(我知道C中没有字符串),然后我可以将requet传递给调用方(也是一个dll,但用C#编写)

因为在C中,这样的事情是不可能的:

char z88rlog;
z88rlog="First log-entry\n";
z88rlog+="Second log-entry\n";
我有两种可能:

  • char z88rlog[真的很大]
  • 动态分配内存
  • 在我看来,第一种方法是被忽略,因为:

    • 内存的潜在浪费相当巨大
    • 我可能仍然需要比
      更大的内存,从而造成缓冲区溢出
    这给我留下了第二条路。我在这方面做了一些工作,并提出了两个解决方案,其中任何一个都不能正常工作

    /* Solution 1 */    
    void logpr(char* tmpstr)
    {
        extern char *z88rlog;
        if (z88rlog==NULL)
        {
            z88rlog=malloc(strlen(tmpstr)+1);
            strcpy(z88rlog,tmpstr);
        }
        else
        {
            z88rlog=realloc(z88rlog,strlen(z88rlog)+strlen(tmpstr));
            z88rlog=strcat(z88rlog,tmpstr);
        }
    }
    
    在解决方案1(相当于解决方案2)中,我通过
    char tmpstr[255]传递我的新日志条目。我的“日志文件”
    z88rlog
    是全局声明的,所以我需要
    extern
    来访问它。然后检查是否为
    z88rlog
    分配了内存。如果否,我将分配日志条目的内存大小(+1表示我的
    \0
    ),并将
    tmpstr
    的内容复制到
    z88rlog
    中。如果是,则我会将
    z88rlog
    的内存重新分配为原来的大小+tmpstr
    的长度(+1)。然后使用
    strcat
    将两个“字符串”连接起来。在直接窗口中使用断点,我获得了以下输出:

    z88rlog
    0x00000000 <Schlechtes Ptr>
    z88rlog
    0x0059ef80 "start Z88R version 14OS"
    z88rlog
    0x0059ef80 "start Z88R version 14OS
    opening file Z88.DYNÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««þîþîþîþ"
    
    在这里,我的目标是创建日志文件的副本,释放原始文件的内存,以新的大小为原始文件创建新内存,并将内容复制回来。不要忘记释放临时副本,因为它是通过malloc分配的。当它到达
    空闲时,它会立即崩溃,再次告诉我堆可能被破坏

    因此,让我们暂时不发表评论。这确实工作得更好——让我松了一口气——但在构建日志字符串时,并不是所有来自
    z88rlogtmp
    的字符都被复制了。但一切都正常工作。直到突然,我再次被告知堆可能被破坏,调试器在malloc.c中的
    中的
    的末尾放置了一个断点。根据调试器,该值为1041

    因此,我有2(或3)种方法来实现这种“字符串增长”,但没有一种有效。给出大小的错误是否会让我得出阵列变得太大的结论?我希望我解释清楚我想做什么,有人可以帮助我:-)提前谢谢


    讽刺的是,我应该去买一些新的电脑堆。它是否适合在RAM插槽中?谁能推荐一个好品牌?讽刺一下你似乎有很多问题。首先,在您的
    realloc
    调用中,您不为终止的
    '\0'
    字符分配空间。在第二个解决方案中,您的strlen(tmpstr+1)
    不正确。在第二个解决方案中,您还可以使用strcat将数据追加到现有缓冲区
    z88rlog
    ,如果缓冲区不够大,您可以覆盖未分配的内存,或者覆盖为其他内容分配的数据。strcat
    的第一个参数是目的地,这也是函数返回的内容,因此您也会释放新分配的内存


    第一个解决方案是使用
    realloc
    ,如果您只记得分配额外的字符,应该可以很好地工作。

    您似乎有很多问题。首先,在您的
    realloc
    调用中,您不为终止的
    '\0'
    字符分配空间。在第二个解决方案中,您的strlen(tmpstr+1)
    不正确。在第二个解决方案中,您还可以使用strcat将数据追加到现有缓冲区
    z88rlog
    ,如果缓冲区不够大,您可以覆盖未分配的内存,或者覆盖为其他内容分配的数据。strcat
    的第一个参数是目的地,这也是函数返回的内容,因此您也会释放新分配的内存

    第一个解决方案是
    realloc
    ,如果您只记得分配额外的字符,它应该可以正常工作。

    这是解决方案1中的一个错误:

    因为没有为终止的空字符分配空间。请注意,您必须将
    realloc()
    的结果存储到临时变量中,以避免出现故障时内存泄漏。要更正:

    char* tmp = realloc(z88rlog, strlen(z88rlog) + strlen(tmpstr) + 1);
    if (tmp)
    {
        z88rlog = tmp;
        /* ... */
    }
    
    z88rlogtmp=malloc(strlen(z88rlog) + strlen(tmpstr) + 1);
    

    解决方案2中的错误:

    /* Solution 2 */
    void logpr(char* tmpstr)
    {
        extern char *z88rlog;
        char *z88rlogtmp;
        if (z88rlog==NULL)
        {
            z88rlog=malloc(strlen(tmpstr)+1);
            strcpy(z88rlog,tmpstr);
        }
        else
        {
            z88rlogtmp=malloc(strlen(z88rlog)+strlen(tmpstr+1));
            z88rlogtmp=strcat(z88rlog,tmpstr);
            free(z88rlog);
            z88rlog=malloc(strlen(z88rlogtmp)+1);
            memcpy(z88rlog,z88rlogtmp,strlen(z88rlogtmp)+1);
            free(z88rlogtmp);
        }
    }
    
    它的计算长度小于
    tmpstr
    。要更正:

    char* tmp = realloc(z88rlog, strlen(z88rlog) + strlen(tmpstr) + 1);
    if (tmp)
    {
        z88rlog = tmp;
        /* ... */
    }
    
    z88rlogtmp=malloc(strlen(z88rlog) + strlen(tmpstr) + 1);
    
    指针重新分配导致未定义的行为:

        z88rlogtmp=strcat(z88rlog,tmpstr);
        /* Now, 'z88rlogtmp' and 'z88rlog' point to the same memory. */
    
        free(z88rlog);
        /* 'z88rlogtmp' now points to deallocated memory. */
    
        z88rlog=malloc(strlen(z88rlogtmp)+1);
        /* This call   ^^^^^^^^^^^^^^^^^^ is undefined behaviour,
           and from this point on anything can happen. */
    
        memcpy(z88rlog,z88rlogtmp,strlen(z88rlogtmp)+1);
        free(z88rlogtmp);
    

    此外,如果代码在Web服务器中执行,那么几乎可以肯定它是在多线程环境中运行的。由于您有一个全局变量,因此需要对其进行同步访问。

    这是解决方案1中的一个错误:

    因为没有为终止的空字符分配空间。请注意,您必须将
    realloc()
    的结果存储到临时变量中,以避免出现故障时内存泄漏。要更正:

    char* tmp = realloc(z88rlog, strlen(z88rlog) + strlen(tmpstr) + 1);
    if (tmp)
    {
        z88rlog = tmp;
        /* ... */
    }
    
    z88rlogtmp=malloc(strlen(z88rlog) + strlen(tmpstr) + 1);
    

    解决方案2中的错误:

    /* Solution 2 */
    void logpr(char* tmpstr)
    {
        extern char *z88rlog;
        char *z88rlogtmp;
        if (z88rlog==NULL)
        {
            z88rlog=malloc(strlen(tmpstr)+1);
            strcpy(z88rlog,tmpstr);
        }
        else
        {
            z88rlogtmp=malloc(strlen(z88rlog)+strlen(tmpstr+1));
            z88rlogtmp=strcat(z88rlog,tmpstr);
            free(z88rlog);
            z88rlog=malloc(strlen(z88rlogtmp)+1);
            memcpy(z88rlog,z88rlogtmp,strlen(z88rlogtmp)+1);
            free(z88rlogtmp);
        }
    }
    
    它的计算长度小于
    tmpstr
    。要更正:

    char* tmp = realloc(z88rlog, strlen(z88rlog) + strlen(tmpstr) + 1);
    if (tmp)
    {
        z88rlog = tmp;
        /* ... */
    }
    
    z88rlogtmp=malloc(strlen(z88rlog) + strlen(tmpstr) + 1);
    
    指针重新分配导致未定义的行为:

        z88rlogtmp=strcat(z88rlog,tmpstr);
        /* Now, 'z88rlogtmp' and 'z88rlog' point to the same memory. */
    
        free(z88rlog);
        /* 'z88rlogtmp' now points to deallocated memory. */
    
        z88rlog=malloc(strlen(z88rlogtmp)+1);
        /* This call   ^^^^^^^^^^^^^^^^^^ is undefined behaviour,
           and from this point on anything can happen. */
    
        memcpy(z88rlog,z88rlogtmp,strlen(z88rlogtmp)+1);
        free(z88rlogtmp);
    

    此外,如果代码在Web服务器中执行,则几乎可以确定