好的,所以我有下面的代码在C#中将一个字符串附加到另一个,注意这只是一个例子,所以在C#中给出替代字符串连接方法并不是必须的,这只是为了简化示例.
string Data = ""; Data +="\n\nHTTP/1.1 " + Status_code; Data += "\nContent-Type: " + Content_Type; Data += "\nServer: PT06"; Data += "\nContent-Length: " + Content_Lengt; Data += "\nDate: " + Date; Data += "\n" + HTML;
现在我想在C中做同样的事情,我试图通过以下方式做到这一点
time_t rawtime; time ( &rawtime ); char *message = "\n\nHTTP/1.1 "; message = strcat(message, Status_code); message = strcat(message, "\nContent-Type: "); message = strcat(message, Content_Type); message = strcat(message, "\nServer: PT06"); message = strcat(message, "\nContent-Length: "); message = strcat(message, Content_Lengt); message = strcat(message, "\nDate: "); message = strcat(message, ctime(&rawtime)); message = strcat(message, "\n"); message = strcat(message, HTML);
现在,这给了我一个Segment故障,我知道为什么,我访问和读取内存,我不应该.但问题是,我该如何解决?我可以使用string.h,就像我在C#中一样吗?
更改
char *message = "\n\nHTTP/1.1 ";
至
char message[1024]; strcpy(message,"\n\nHTTP/1.1 ");
你应该没问题,总消息长度为1023.
编辑:(根据mjy的评论).以这种方式使用strcat是获得缓冲区溢出的好方法.您可以随时编写一个小函数来检查缓冲区的大小和传入字符串添加的长度以克服此问题,或者在动态缓冲区上使用realloc.IMO,程序员有责任检查使用它们的正确缓冲区大小,就像sprintf和其他C字符串函数一样.我假设出于性能原因,C正在使用C++,因此STL不是一个选项.
编辑:根据Filip评论的请求,一个基于固定大小的char缓冲区的简单strcat实现:
char buffer[MAXSIZE] = ""; int mystrcat(char *addition) { if (strlen(buffer) + strlen(addition) + sizeof(char) >= MaxSize) return(FAILED); strcat(buffer,addition); return(OK); }
使用动态分配:
char *buffer = NULL; int mystrcat(char *addition) { buffer = realloc(buffer, strlen(buffer) + strlen(addition) + sizeof(char)); if (!buffer) return(FAIL); strcat(buffer, addition); return(OK); }
在这种情况下,您必须在完成后手动释放缓冲区.(由C++等价物中的析构函数处理)
附录(Pax):
好的,既然你没有真正解释为什么你必须创建message[1024]
,这里就是.
使用char*x ="hello"时,实际字节('h','e','l','l','o',0)(末尾为null)存储在与内存区分开的区域中变量(很可能是只读的)和变量x设置为指向它.在null之后,可能还有其他非常重要的东西.所以你根本无法附加.
有了char x[1024]; strcpy(x,"hello");
,你首先分配1K om内存,完全专用于x.然后你将"hello"复制到其中,并在最后留下相当多的空间来附加更多的字符串.在你追加超过1K的允许数量之前,你不会遇到麻烦.
最终附录(Pax):
我不知道为什么没有人提到snprintf()
的stdio.h
呢.这是输出多个值的C方式,您甚至不必事先将基元转换为字符串.
以下示例使用堆栈分配的固定大小的缓冲区.否则,您必须malloc()
使用缓冲区(并存储其大小),这样就可以realloc()
在溢出时...
char buffer[1024]; int len = snprintf(buffer, sizeof(buffer), "%s %i", "a string", 5); if(len < 0 || len >= sizeof(buffer)) { // buffer too small or error }
编辑:您也可以考虑使用该asprintf()
功能.它是一个广泛使用的GNU扩展,是TR 24731-2的一部分(这意味着它可能会成为下一个C标准).上面的例子会读到
char * buffer; if(asprintf(&buffer, "%s %i", "a string", 5) < 0) { // (allocation?) error }
free()
使用它时请记住缓冲区!
从使用更安全的strncat
功能开始.通常总是使用更安全的'n'函数,如果字符串的大小大于特定大小,则不会溢出.
在C中,您需要自己处理字符串大小.因此,您需要知道生成的字符串有多大并适应它.如果您知道左侧所有字符串的大小,则应创建一个足以容纳结果字符串的缓冲区.