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