LINUX.ORG.RU

[C] segfault при модификации строки

 


0

1

Привет, ЛОР! Пишу для разминки калькулятор. Дописался вот, что оно падает, хотя вроде-бы я в других программах делал так же, ничего не падало.

Погуглил бы, да не знаю, что именно нужно. Подскажите, пожалуйста.

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

double
next_expr (char expr[])
{
  double tv, r;
  char *ns;
  size_t p, len;
  unsigned int act;
  
  tv  = 0;
  r   = 0;
  len = strlen (expr);
  ns  = NULL;
  enum  ACT {ADD, SUB, MUL, DIV};
  
  switch (expr[0])
    {
    case '+':
      act = ADD;
    case '-':
      act = SUB;
    }
  
  for (size_t i = 1; i < len; i++)
    {
      
      if (ns == NULL && isdigit (expr[i]))
        ns = &expr[i];
      else
        if (isspace (expr[i]))
          {
            printf ("%d\n", i);
            expr[i] = '\0';
            sscanf (ns, "%lf", &tv);
            switch (act)
              {
              case ADD:
                r += tv;
              }
            ns = NULL;
          }
    }
  return r;
}

int
main (void)
{
  char *expr = "+ 1 2 3 ";
  
  printf ("%lf\n", next_expr(expr));
  return EXIT_SUCCESS;
}

age@normandy:~/Sources$ ./nc 
1
Segmentation fault

-----

Starting program: /home/age/Sources/nc 

Program received signal SIGSEGV, Segmentation fault.
0x08048547 in next_expr (expr=0x8048694 "+ 1 2 3 ") at nc.c:36
37		    expr[i] = '\0';


Переменная expr указывает на константную строку в read-only сегменте данных. Её нельзя менять. Попробуй выделить память под строку динамически.

anonymous
()

Анонимус прав. Ещё как вариант ещё можно написать так: ... int main (void) { char expr[] = «+ 1 2 3 »; ... }

Fawkes
()

> Погуглил бы, да не знаю, что именно нужно. Подскажите, пожалуйста.

Подсказываю: запускать компилятор надо с опцией -Wall , и вдумчиво читать все, что он тебе напишет.

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

лучше -Wall -Werror ))

но в данном случае это не поможет, так как в программе два сегфолта ))

-char *expr = «+ 1 2 3 »;
+char expr[] = «+1 2 3 »;

второй сегфолт из-за отсутствия должных проверок перед вызовом sscanf.

dimon555 ★★★★★
()

еще ты не знаешь про switch и будешь получать 0.0 всегда

rg-400
()

Про char *expr вам уже сказали, а где break'и?

andreyu ★★★★★
()

> char *expr = «+ 1 2 3 »;

Добавь в парсер скобочки и пиши сразу лисп, чо!

yoghurt ★★★★★
()

Пожалуй все уже рассказали выше, кроме того, что переменные можно инициализировать при объявлении и что правилом хорошего тона для функций является минимум побочных эффектов - т.е. лучше модифицировать в next_expr копию переданной строки. А то в вашем коде никто не сможет потом разобраться.

amomymous ★★★
()

А еще сегфолты хорошо помогает искать утилита valgrind

AIv ★★★★★
()

break'и в switch забыл, да. и строка-то в read-only памяти находится.

do0dlez ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.