程序.exe(c) (malloc) 已停止工作



嗨,我写了这段代码,它有效,但最终,"程序已停止工作">

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
void main() 
{
char *s;
s=(char*)malloc(sizeof(char));
printf("Enter a string:n");
gets(s);
while (*s)
{
if (*s>= 65 && *s<=90)
printf("%c",*s+32);
else if(*s>=97 && *s<=122)
printf("%c",*s-32);
else
printf("%c",*s);
*s++;
}
free(s);
}

该代码不起作用,实际上它具有未定义的行为。

这:

s = (char *) malloc(sizeof(char));

分配 1 字节的存储,然后将字符串扫描到其中,因此很可能导致缓冲区溢出。缓冲区只能保存单个字符串,即末尾终止符字符之前的 0 个字符的字符串。

你的意思是:

s = malloc(128);

或类似的东西。

无需强制转换,并且sizeof (char)始终为 1,因此不会添加任何内容。

此外,作为更多的代码审查,代码中的幻数通常被认为是一个坏主意,而是写:

if (*s >= 'A' && *s <= 'Z')

甚至更好

if (isupper((unsigned int) *s))

不对 ASCII 上的 depdency 进行硬编码。

更新哦,正如评论中指出的那样,您不能更改s的值,然后将更改的值传递给free(),这也是未定义的行为。传递给free()的地址必须与您从malloc()那里取回的地址相同。

使用单独的变量进行迭代:

char *p = s;

并且只free()原始s.

首先,通过s=(char*)malloc(sizeof(char));,您只为缓冲区分配了 1 字节的内存。分配足够的内存来存储输入。还要避免对结果进行类型转换malloc()。更好的版本看起来像

s = malloc(MAX * sizeof(*s));/* MAX is num of bytes you need to define */

其次,不要使用gets()而使用fgets()。阅读man 3 gets或检查 https://linux.die.net/man/3/gets

最后使用int main(void) { }而不仅仅是main(){ }

更重要的是,当您在那个时候执行free(s)时,s不会指向由于s++而先前分配给它的内存,因此可能会导致错误,例如

free(): 无效指针:

因此,在迭代时不要更改s使用s[row]或者您可以将s分配给其他指针,然后您可以执行free(s)

完整代码

int main() {
char *s = NULL;
int size = MAX*sizeof(*s);/*define MAX value, it is no of bytes need*/
s = malloc(size);/* this is generic
sizeof(*s) works for any data type */
printf("Enter a string:n");
fgets(s,size,stdin);/* use fgets() instead of gets() */
int row = 0;
while (s[row]!='') {
if ( *(s+row) >= 65 && *(s+row) <= 90)
printf("%c",*(s+row) + 32);
else if( *(s+row) >=97 && *(s+row) <= 122)
printf("%c",*(s+row) - 32);
else
printf("%c",*(s+row));
row++;
}
free(s);/* s still points to same location */
return 0;
}

您也可以使用isupper()而不是比较每个字符 ASCII 值。

这是错误的。

s = (char*)malloc(sizeof(char));
printf("Enter a string:n");
gets(s);

s = (char*)malloc(sizeof(char));分配 1 个字节的内存。然后用gets(s);你得到一个字符串,它将是未定义的行为。

您必须将其更改为

s = malloc(MAX_LENGTH * sizeof(char));   //MAX_LENGTH is user defined

此外,您必须检查malloc()是否返回了任何内容。如果它返回NULL则意味着没有分配内存,所有现有程序都将调用未定义的行为。 此外,无需强制转换malloc结果,因此要进一步改进代码,您需要将其更改为,

s = malloc(MAX_LENGTH * sizeof(char));
if(s == NULL)
{
// Add error handling here
}

void main()

不再是标准,请参阅这篇文章,其中解释了原因。如果您想知道 C11 标准对此有何规定,请参阅此处的标准: 第 5.1.2.2.1 节 程序启动

所以把它改成,

int main(void)

您应确保仅在分配free(s);时才调用它。正如下面的评论之一正确指出free(NULL);不是问题,但它也没有影响,所以为什么要称呼它。

再次指出sNULL,但它与这段代码无关。

最新更新