Ошибка сегментации с массивом строк - PullRequest
0 голосов
/ 30 ноября 2010

У меня возникли некоторые проблемы с массивом строк, которые, кажется, занимают зарезервированное пространство памяти. Код слишком велик для размещения здесь, поэтому я опубликую важную часть ниже:

int main (  ){

 int i = 0, j = 0, k = 0, count = 0, numLinhas = 0, l = 0;
 char string[100][100];
 char line [17];
 char str[4];
 char str1[5];
 char str2[4];
 char str3[4];

 FILE *p;
 p = fopen("text.txt", "r");
 while(fgets(line, sizeof line, p)!=NULL){
  printf("%s", line);
  strncpy(string[i], line, 17);
  i++;
  numLinhas++; 
  }  
  fclose(p);
  char *temp[numLinhas]; 

После этого он входит в цикл, в котором сохраняет в string [i] значение оператора, содержащегося в файле. Начало for и три примера приведены ниже:

    for (i = 0; i<numLinhas; i++){
    sscanf( string[i], "%s %s %s %s" ,str1, str,str2, str3);
    if(str[0]=='0' && str[1] == '0' && str[2]!= 'd') {
    temp[i] = "NOP";
    count++;
    }
    if(str[0]=='0'&& str[1] == '6' && str[2]!= 'd') {
    sprintf(temp[i],"%s,%s" , "MVI B", str2);
    count = count+2;
    }

    if(str[0]=='0'&& str[1] == '7' && str[2]!= 'd') {
    temp[i] = "RLC";
    count++;
    }

Ошибка случайная - это не всегда происходит. И это обычно происходит, когда есть вызов sprintf. О да! Ниже приведен txt-файл, который я загружаю в качестве примера:

0000 21a 11r 00r
0003 7Ea
0004 21a 12r 00r
0007 46a
0008 80a
0009 21a 13r 00r
000C 77a
000D 3Ea 01a
000F 3Da
0010 76a
0011 0Ad
0012 03d
0013 01d

Просто увидел что-то новое. вот окно компиляции, которое я получаю:

marcos@john:~/Desktop$ ./paraler
0000 21a 11r 00rValor de l: 16

Valor de l: 1
0003 7Ea
Valor de l: 9
0004 21a 12r 00rValor de l: 16

Valor de l: 1
0007 46a
Valor de l: 9
0008 80a
Valor de l: 9
0009 21a 13r 00rValor de l: 16

Valor de l: 1
000C 77a
Valor de l: 9
000D 3Ea 01a
Valor de l: 13
000F 3Da
Valor de l: 9
0010 76a
Valor de l: 9
0011 0Ad
Valor de l: 9
0012 03d
Valor de l: 9
0013 01d
Valor de l: 9
string:0000 21a 11r 00r
string:

string:0003 7Ea

string:0004 21a 12r 00r
string:

string:0007 46a

string:0008 80a

string:0009 21a 13r 00r
string:

string:000C 77a

string:000D 3Ea 01a

string:000F 3Da

string:0010 76a

string:0011 0Ad

string:0012 03d

string:0013 01d

Segmentation fault

Странно, что я получаю несколько пустых мест в массиве строк ... Это как-то связано с ошибкой?

Ответы [ 3 ]

1 голос
/ 30 ноября 2010

Вы выделяете память для каждого temp[i] перед вызовом sprintf? Если нет, то есть ваша проблема.

if (!strncmp(str, "06", 2) && str[2] != 'd')
{
  temp[i] = malloc(5 + strlen(str2) + 2);  // Thanks, philippe
  if (temp[i])
    sprintf(temp[i], "%s,%s", "MVI B", str2);
}

Хотя теперь вам придется отслеживать, какие элементы temp были выделены с помощью malloc, чтобы вы могли их позже освободить.

Редактировать

В конце вашей программы вы можете перебрать массив temp и проверить содержимое каждого элемента на соответствие ведущей части вашей строки, указанной выше, и, если они совпадают, освободить этот элемент, используя free:

for (i = 0; i < numLinhas; i++)
{
  if (strcnmp(temp[i], "MVI B", strlen("MVI B")) == 0)
    free(temp[i]);
}

Вам не нужно делать это для элементов массива, которым были назначены «NOP» или «RLC»; в этих случаях вы просто копировали адрес строкового литерала в элемент массива. Для этих элементов не было выделено никакой новой памяти, поэтому вам не нужно беспокоиться об их освобождении.

0 голосов
/ 30 ноября 2010
if(str[0]=='0'&& str[1] == '6' && str[2]!= 'd') {
    /* allocate memory to store instruction - to be freed later */  
    temp[i] = malloc(5 + strlen(str2) + 2); /* +2 for the comma */
    sprintf(temp[i],"%s,%s" , "MVI B", str2);
    count = count+2;
    }

Проблема возникает, когда встречается мнемоника, начинающаяся с 06 и не заканчивающаяся на d; sprintf() пишет в нераспределенной области, поскольку temp [i] не инициализировано Вы должны выделить место для хранения результата sprintf.

0 голосов
/ 30 ноября 2010

Есть некоторые проблемы, которые я вижу сразу:

изменить первый пункт может не относиться к вашей среде, но вы должны иметь это в виду

  • Вы пытаетесь создать char *temp[numLinHas] из целого числа, значение которого будет определено во время выполнения. Это допустимо в C99 или может быть предоставлено через расширение компилятора, но в более старых стандартах C размеры массивов должны быть известны во время компиляции. Ваш код может действительно делать это:

    int numLinHas = 0;
    char *temp[numLinHas];
    
  • Другая проблема заключается в том, что когда вы делаете sprintf, вы пытаетесь скопировать что-то в temp без выделения памяти для указателя для хранения строки.

...