【问题标题】:program crashes on closing关闭时程序崩溃
【发布时间】:2014-09-03 09:03:12
【问题描述】:

所以,这是我第一次在这里发帖,我会尽可能具体。 我必须为我的学校制作一个程序,上面写着:

先写一个获取字符并返回的函数:

  1. 如果是大写字母,则为相同的字符。
  2. 如果是小写字母,则为大写字母。
  3. 反斜杠 ('\') 如果是数字。
  4. 在任何其他情况下为星号 ('*')。

然后,使用您的函数,创建一个程序,获取字符串并在函数更改后重新打印它。它应该一直要求一个新字符串,直到用户输入“QUIT”,在这种情况下,它将打印“Bye!”然后退出。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

char fnChange(char c)
{
     if (c > 'a'-1 && c < 'z'+1)
          c = c - 32;
     else if (c > '0'-1 && c < '9'+1)
          c = '\\' ;
     else if ( c > 'A'-1 && c < 'Z'+1)
          c = c;
     else 
          c = '*';
     return c;
}


int main()
{   
    int i, refPoint;
    char *str = (char*)malloc(10);
    //without the next one, the program crashes after 3 repeats.
    refPoint = str;
    while (1==1) {            
       printf("Give a string: ");
       str = refPoint;//same as the comment above.
       free(str);
       scanf("%s",str);
         if (*str == 'Q' && *(str+1) == 'U' && *(str+2) == 'I' && *(str+3) == 'T') {
           // why won't   if (str == 'QUIT')   work?
           free(str);
           printf("Bye!");     //after printing "Bye!", it crashes.
           system("pause");    //it also crashes if i terminate with ctrl+c.
           exit(EXIT_SUCCESS); //or just closing it with [x].
         }       
         printf("The string becomes: ");
         while (*str != '\0') {
           putchar(fnChange(*str));
           str++;
         }
      printf("\n");
    }
}

【问题讨论】:

  • str = refPoint?????
  • free(str) 然后scanf("%s",str)????你到底希望发生什么???
  • 一个小问题(您的代码存在真正的问题,请参阅下面 Joachim 的回答),而不是 c &gt; 'a'-1,您真的应该写 c &gt;= 'a'。或者,更好的是,只需使用islower()
  • refPoint = str;? refPoint 不是指针!
  • “为什么如果 (str == 'QUIT') 不起作用?” - 因为你需要像 strcmp() 这样的函数来比较字符串:if( strcmp( str, "QUIT" ) == 0 ) { .. }

标签: c crash


【解决方案1】:
free(str);
scanf("%s",str);

Big 不,不,在你释放它之后你不能使用动态分配的内存。最重要的是,您在循环中再次释放它。

这样做是未定义的行为。这几乎肯定是导致您崩溃的原因。

其他几个问题。您可以使用&lt;= 而不是&lt; 使您的代码更具可读性,例如:

if  ((c >= 'a') && (c <= 'z')) ...

使用像32 这样的magic 数字几乎总是一个坏主意。如果您使用字母连续的编码(例如 ASCII),您可以这样做:

c = c - 'A' + 'a';

把大写变成小写。

真正应该做的是使用toupper()tolower()(以及isupper()islower(),以检测大小写),因为这些字母是保证是连续的。

表达式str == 'QUIT' 不会像你想的那样做,因为'QUIT' 不是字符串。相反,它是一个多字节字符文字。然而,即使str == "QUIT" 也不会像你想的那样做,因为在 C 中比较字符串的正确方法是:

if (strcmp (str, "QUIT") == 0) ...

【讨论】:

    【解决方案2】:

    您的代码中有多个undefined behavior

    首先你分配一个指向整数变量的指针。这些并不是真正兼容的(例如,想想如果int 的大小是 32 位而指针的大小是 64 位会发生什么)。

    然后在使用前释放已分配的指针,从而写入未分配的内存。

    然后你再次在同一个指针上调用free

    【讨论】:

      【解决方案3】:

      这可能导致崩溃的原因有多种。按照您的代码顺序,或多或少:

      free str 然后对其进行 scanf 。一旦你释放了内存,它就不再可用了。

      然后是scanf:scanf("%s", str)。一旦有人在控制台输入 10 个或更多字符的字符串,您就会进入未定义行为的领域,因为内存将被覆盖。

      str 分配给refpoint,反之亦然,应该会给您带来大量编译器警告。您的一个变量是int,另一个是char *。在某些架构上,指针不适合int,并且您的程序会在您使用它时立即崩溃。

      您的 while 循环递增 str。如果没有来自refpoint 的(危险)副本,您最终将尝试释放不是malloc 结果的指针。这是未定义的行为,可能会崩溃。

      顺便说一句:

      请不要转换malloc 的结果。它返回一个 void * 并且在 C 中您可以将 void * 分配给任何东西,并且不必要的强制转换会降低代码的可读性。选角意味着您正在做一些不寻常的事情,而该分配不是。

      你不能这样做 str == 'QUIT' 因为 C 编译器会将字符串的地址与 - 好吧,键入 'QUIT' 的效果取决于编译器。它可能会将其与“Q”的字符值进行比较。即使使用str == "QUIT",它也会将指针str(即malloc返回的地址)的值与字符串“QUIT”的地址进行比较,这将是链接器设计用来存储它的任何地方。 C不做字符串比较,你必须使用strcmp

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-06
        • 2013-12-12
        • 1970-01-01
        • 1970-01-01
        • 2017-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多