我正在尝试创建一个动态字符"字符串指针" / array并且我的代码不会打印值,输入的字符超过249个字符。我只是想知道字符数组/"字符串指针"是否有最大返回长度。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *input() {
char *inpt;
char check;
int i;
int count;
i = 0;
count = 1;
check = '\0';
inpt = (char*)malloc(1);
while (check != '\n') {
check = getchar();
if (check == '\n') {
break;
} else {
inpt[i] = check;
i++;
count++;
inpt = realloc(inpt, count);
}
}
inpt[i] = '\0';
char *retrn;
retrn = inpt;
free(inpt);
printf("%d \n", i);
return retrn;
}
int main(int argc, char **argv) {
char *name;
printf("Please print name: \n");
name = input();
printf("%s is the name \n", name);
return 0;
}
答案 0 :(得分:4)
问题不在于您尝试返回的字符串的长度,而是返回指向不再分配给您的内存的指针:
char *retrn;
retrn = inpt;
free(inpt);
return retrn;
当你执行retrn = inpt
时,你不会复制内存,而是有两个指针指向同一个内存。然后你free
那个记忆并返回一个指向新自由记忆的指针。该指针当然不能被解除引用,任何这样做的尝试都会导致未定义的行为。
解决方案不是retrn
之类的任何临时变量,而是free
函数中的input
内存。而是返回inpt
并在调用函数(在您的情况下为main
)中free
内存。
答案 1 :(得分:2)
这很可能是因为使用了空闲内存。您对retrn的分配输入不会创建另一个副本。您将获得未定义的行为,可能包括您正在经历的行为。
答案 2 :(得分:2)
继续我的评论,有许多方案可以动态分配内存。从效率的角度来看,你想要避免的一件事是不必要地为每个角色重新分配。不是为添加到名称的每个字符调用realloc
,而是分配合理数量的字符来保存名称,如果达到该数量,则重新分配,将当前分配大小加倍,更新保持当前大小的变量并保持去。
您已有数组索引,因此无需单独保留count
。只需使用您的数组索引作为计数器,确保您至少有index + 1
个字符可用于为 nul-terminate inpt
提供空间。
无需在input()
中保留单独的指针。只需为inpt
分配并在完成后返回inpt
作为指向内存块的指针。 (不要忘记free (name);
中的main()
,这将释放您在input
中分配的内存。
永远不要直接realloc
指针。 (例如,不要inpt = realloc (inpt, size);
)如果realloc
失败,则返回NULL
,导致丢失指向inpt
之前引用的已分配块realloc
的指针呼叫。而是使用临时指针,验证realloc
是否成功,然后将新块分配给inpt
(下面的示例)
完全放弃,你可以做类似的事情:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MEMSZ 32 /* initial allocation size (must be at least 1) */
char *input (void)
{
char *inpt = NULL, check;
size_t mem = MEMSZ, ndx = 0;
if (!(inpt = malloc (mem))) { /* allocate/validate mem chars */
fprintf (stderr, "input() error: virtual memory exhausted.\n");
return NULL;
}
/* you must check for EOF in addition to '\n' */
while ((check = getchar()) && check != '\n' && check != EOF)
{ /* check index + 1 to insure space to nul-terminate */
if (ndx + 1 == mem) { /* if mem limit reached realloc */
void *tmp = realloc (inpt, mem * 2); /* use tmp ptr */
if (!tmp) { /* validate reallocation */
fprintf (stderr, "realloc(): memory exhausted.\n");
break; /* on failure, preserve existing chars */
}
inpt = tmp; /* assign new block of memory to inpt */
mem *= 2; /* set mem to new allocaiton size */
}
inpt[ndx++] = check; /* assign, increment index */
}
inpt[ndx] = 0; /* nul-terminate */
return inpt; /* return pointer to allocated block */
}
int main (void)
{
char *name = NULL;
printf ("Please enter name: ");
if (!(name = input())) /* validate input() succeeded */
return 1;
printf ("You entered : %s\n", name);
free (name); /* don't forget to free name */
return 0;
}
示例使用/输出
$ ./bin/entername
Please enter name: George Charles Butte
You entered : George Charles Butte
内存使用/错误检查
在你编写的动态分配内存的任何代码中,你有2个职责关于任何分配的内存块:(1)总是保留一个指向起始地址的指针内存块,(2)当不再需要时,它可以释放。
您必须使用内存错误检查程序,以确保您不会尝试在已分配的内存块的范围之外/之外进行写入,尝试读取或基于未初始化值的条件跳转,最后,确认您释放了已分配的所有内存。
对于Linux valgrind
是正常的选择。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。
$ valgrind ./bin/entername
==2566== Memcheck, a memory error detector
==2566== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==2566== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==2566== Command: ./bin/entername
==2566==
Please enter name: George Charles Butte
You entered : George Charles Butte
==2566==
==2566== HEAP SUMMARY:
==2566== in use at exit: 0 bytes in 0 blocks
==2566== total heap usage: 1 allocs, 1 frees, 32 bytes allocated
==2566==
==2566== All heap blocks were freed -- no leaks are possible
==2566==
==2566== For counts of detected and suppressed errors, rerun with: -v
==2566== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认已释放已分配的所有内存并且没有内存错误。
如果您有任何其他问题,请与我们联系。
答案 3 :(得分:1)
数组的大小存在内在限制:
malloc()
如果由于缺少核心内存而无法履行请求,则realloc()
可能会返回NULL
。您一定要检查malloc()
和realloc()
是否成功。size_t
类型的最大值:SIZE_MAX
,其最小值为65535
,但您使用的类型为int
对malloc()
或realloc()
的请求,其范围可能小于size_t
。在大多数当前桌面系统上,类型int
是32位,其中size_t
可能是64位,可用内存可能远远超过2GB。使用size_t
代替int
。但请注意,您的问题来自一个更简单的错误:您释放为字符串分配的内存块并返回指针的副本,该指针现在指向释放的内存。访问此内存具有未定义的行为,可以是任何内容,包括最多249个字节的明显正确行为和超出的故障。
另请注意,您应对int
使用check
类型,并将getchar()
的返回值与EOF进行比较,以避免在输入不包含换行符时无限循环(例如空文件。)
以下是更正后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *input(void) {
char *p = malloc(1); /* simplistic reallocation, 1 byte at a time */
size_t i = 0; /* use size_t for very large input */
int c; /* use int to detect EOF reliably */
if (p == NULL) {
return NULL; /* allocation error */
}
while ((c = getchar()) != EOF && c != '\n') {
char *newp = realloc(p, i + 2);
if (newp == NULL) {
free(p); /* avoid a memory leak */
return NULL; /* reallocation error */
}
p = newp;
p[i++] = c;
}
if (i == 0 && c == EOF) {
free(p);
return NULL; /* end of file */
}
p[i] = '\0';
return p;
}
int main(int argc, char **argv) {
char *name;
printf("Please print name: ");
name = input();
if (name == NULL) {
printf("input() returned NULL\n");
} else {
printf("%s is the name\n", name);
free(name);
}
return 0;
}
答案 4 :(得分:1)
C
中的字符数组是否有最大返回长度
字符数组的最大大小为SIZE_MAX
。 SIZE_MAX
至少为65535。
我只是想知道字符数组/“字符串指针”是否有最大返回长度。
对于字符串,其最大大小为SIZE_MAX
,最大长度为SIZE_MAX - 1
。