关于动态分配内存,我看到的一个回答感觉太麻烦,该回答传送门
https://segmentfault.com/a/1190000007675747
于是我尝试用 realloc 函数分配内存, 结果只要输出 6 个以上字符,程序就终止,原因搜了半天没找到,难道只能一开始就给字符串分配足够大的空间吗 (菜鸟一枚,才学 C 没几天,求大神轻喷)
#include <stdlib.h>
#include<string.h>
void main() {
char str[6];
char *new_str = str;
//输入 6 个以上的字符
scanf("%s", str);
if (strlen(str)>sizeof str)
{
new_str = (char*)realloc(str, 100*sizeof(char));
}
prin
return 0;
}
第 1 条附言 · 2018 年 12 月 7 日
忘记说一个重点了,因为异常的地方是在 main 函数结尾处异常,所以我想着在函数结束点能不能修补这个越界,才会有这种想法。。
第 2 条附言 · 2018 年 12 月 7 日
又发现传送门也放错了,更正下
https://segmentfault.com/a/1190000000360944
https://segmentfault.com/a/1190000000360944
第 3 条附言 · 2018 年 12 月 7 日
看来也只能用这两种方法了,C 的内存管理确实是真的麻烦。。。
```c
char * getline(void) {
char * line = malloc(100), * linep = line;
size_t lenmax = 100, len = lenmax;
int c;
if(line == NULL)
return NULL;
for(;;) {
c = fgetc(stdin);
if(c == EOF)
break;
if(--len == 0) {
len = lenmax;
char * linen = realloc(linep, lenmax *= 2);
if(linen == NULL) {
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if((*line++ = c) == '\n')
break;
}
*line = '\0';
return linep;
}
```
```c
char* getstr()
{
char* str;
char* _str;
int i = 1;
str = (char*)malloc(sizeof(char) * (i + 1));
while('\n' != (str[i - 1] = getchar()))
{
i ++;
_str = (char*)malloc(strlen(str) + 1);
str[i - 1] = '\0';
strcpy(_str, str);
free(str);
str = (char*)malloc(sizeof(char) * (i + 1));
if(NULL == str)
{
free(_str);
printf("No enough memory!");
return NULL;
}
strcpy(str, _str);
free(_str);
}
str[i - 1] = '\0';
return str;
}
```
```c
char * getline(void) {
char * line = malloc(100), * linep = line;
size_t lenmax = 100, len = lenmax;
int c;
if(line == NULL)
return NULL;
for(;;) {
c = fgetc(stdin);
if(c == EOF)
break;
if(--len == 0) {
len = lenmax;
char * linen = realloc(linep, lenmax *= 2);
if(linen == NULL) {
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if((*line++ = c) == '\n')
break;
}
*line = '\0';
return linep;
}
```
```c
char* getstr()
{
char* str;
char* _str;
int i = 1;
str = (char*)malloc(sizeof(char) * (i + 1));
while('\n' != (str[i - 1] = getchar()))
{
i ++;
_str = (char*)malloc(strlen(str) + 1);
str[i - 1] = '\0';
strcpy(_str, str);
free(str);
str = (char*)malloc(sizeof(char) * (i + 1));
if(NULL == str)
{
free(_str);
printf("No enough memory!");
return NULL;
}
strcpy(str, _str);
free(_str);
}
str[i - 1] = '\0';
return str;
}
```
19 条回复 • 2018-12-07 17:12:23 +08:00
|
1
msg7086 2018 年 12 月 7 日
> 难道只能一开始就给字符串分配足够大的空间吗
当然了。 类比一下。旅行团定酒店,起手先定 3 间双人房,然后来了个 20 个人的团,你说会发生什么事呢。 |
|
2
xjr1022 OP 更正一下,prin 是 printf("%s",new_str);
|
|
5
msg7086 2018 年 12 月 7 日 @xjr1022 越界发生在增大空间之前。程序都炸穿了你稍后再增大空间还有什么用呢。
就像这 20 个人的团在酒店大堂睡了一晚以后,第二天你再去定其他 7 个房间…… |
|
6
kokutou 2018 年 12 月 7 日 起手一个 char *str = malloc(1000 * sizeof(char));
输入超过 1000 就再改大点。 |
|
7
tomychen 2018 年 12 月 7 日 你已经越界在先了
|
|
8
anonymous256 2018 年 12 月 7 日 via Android char str[6]; //你声明它的上限是 6
scanf 在读取时会检查是否溢出。 你可以用 gets 或 fgets(更安全) int main() { char string [256]; fgets (string, 256, stdin); printf ("%s\n",string); return 0; } 参考:http://c.biancheng.net/cpp/html/260.html |
|
10
tomychen 2018 年 12 月 7 日
如果是真的有需要遇到不定长度,就得需要对每次输入处理了,如果只是学习的话,也就是楼上说的定个 256 或者 1024, 用 fgets 或者其他安全函数,也只是把超出的给截掉,而不是动态扩充。
还有 char *argv[]是个好东西 |
|
12
msg7086 2018 年 12 月 7 日 @xjr1022 异常发生在结尾是因为,不是不报,时候未到。
还是拿旅行团做例子。那 20 个人的团有可能当场就来揍你了(比如复写了保护内存,直接 SEGFAULT ),也有可能等回家了以后把你告上法庭(比如复写得不多,直到程序退出清算内存空间的时候才发现内存乱套了)。 |
|
13
xjr1022 OP @msg7086 嗯嗯,是的,也是突发奇想,看来还是骗不了编译器~,果然还是得老老实实得按照传送门里得那种方法才行,谢谢辛苦回复啦 (●'◡'●)
|
|
15
tomychen 2018 年 12 月 7 日
你可以放弃 scanf,当然 很多 C 语言的书里一直在强调这个函数,其实这是个很鸡肋的函数
真要可变简单点就是 int main(int argc, char *argv[]){ //process argv } 然后 就是 getopt() 至于 scanf(),你可以用了 argv 和 getopt 忘了那个它 |
|
16
maokabc 2018 年 12 月 7 日 via Android char str[6];分配在栈上,哪能用 realloc 扩容?
|
|
17
geelaw 2018 年 12 月 7 日 via iPhone @xjr1022 #13 你这个想法是不对的。编译器可以完全不 care 你“骗没骗”它,在你违反标准里的一些规定的时候,受苦的是你自己的程序,而不是编译器——因为你的程序有了未定义行为,它的功能不再有保障。
|
|
18
kljsandjb 2018 年 12 月 7 日 via iPhone
man realloc 先
|
|
19
rochek 2018 年 12 月 7 日 其实,这个地方如果一定要用动态申请内存,是可以做到的
挂钩一下输入函数,重写将输入放进内存的代码 每次放进内存,都 malloc 空间 或者,每次都 realloc 内存 在这段内存用完之后,手动释放下 但是会很麻烦,不如不做 简单的做法就是一开始就申请足够的内存空间 |