c - проблема разыменования - PullRequest
       14

c - проблема разыменования

2 голосов
/ 29 апреля 2010

Я упростил проблему, из-за которой пытался изолировать проблему, но это не помогает.

У меня есть двумерный массив символов для представления памяти. Я хочу передать ссылку на эту симуляцию памяти в функцию. В функции для проверки содержимого памяти я просто хочу перебрать память и распечатать содержимое каждой строки.

Программа выводит первую строку, а затем я получаю ошибку сегмента.

Моя программа выглядит следующим образом:

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

#include <string.h>

void test_memory(char*** memory_ref)  {

    int i;
    for(i = 0; i < 3; i++)  {
        printf("%s\n", *memory_ref[i]);
    }
}

int main()  {
    char** memory;
    int i;
    memory = calloc(sizeof(char*), 20);
    for(i = 0; i < 20; i++)  {
        memory[i] = calloc(sizeof(char), 33);
    }

    memory[0] = "Mem 0";
    memory[1] = "Mem 1";
    memory[2] = "Mem 2";

    printf("memory[1] = %s\n", memory[1]);

    test_memory(&memory);

    return 0;
}

Это дает мне вывод:

memory[1] = Mem 1
Mem 0
Segmentation fault

Если я изменю программу и создаю локальную версию памяти в функции, разыменовав memory_ref, то получу правильный вывод:

Итак:

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

#include <string.h>

void test_memory(char*** memory_ref)  {

    char** memory = *memory_ref;
    int i;
    for(i = 0; i < 3; i++)  {
        printf("%s\n", memory[i]);
    }
}

int main()  {
    char** memory;
    int i;
    memory = calloc(sizeof(char*), 20);
    for(i = 0; i < 20; i++)  {
        memory[i] = calloc(sizeof(char), 33);
    }

    memory[0] = "Mem 0";
    memory[1] = "Mem 1";
    memory[2] = "Mem 2";

    printf("memory[1] = %s\n", memory[1]);

    test_memory(&memory);

    return 0;
}

дает мне следующий вывод:

memory[1] = Mem 1
Mem 0
Mem 1
Mem 2

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

Я не понимаю, почему я должен получить ошибку сегмента во второй раз, и я был бы благодарен за любой совет.

Большое спасибо

Джо

Ответы [ 3 ]

4 голосов
/ 29 апреля 2010

Попробуйте:

printf("%s\n", (*memory_ref)[i]);

Текущая версия эквивалентна

*(*(memory_ref + i));

Это связано с тем, что оператор [] имеет более высокий приоритет, чем разыменование *.Это означает, что когда i больше 0, вы пытаетесь прочитать память после char*** временного memory_ref

Вторая версия равна (*memory_ref)[i], что означает, что вы будете индексировать правильную память.

РЕДАКТИРОВАТЬ: Причина, по которой он работает на первой итерации, заключается в том, что:

*(*(memory_ref + 0)) == *((*memory_ref) + 0)
2 голосов
/ 29 апреля 2010

Это похоже на проблему приоритета. [] Оценивается первым, а * вторым. Для первого примера кода вам понадобится что-то вроде следующего ...

printf("%s\n", (*memory_ref)[i]);
1 голос
/ 29 апреля 2010

Быстрое решение заключается в использовании

printf("%s\n", (*memory_ref)[i]);

Но я подозреваю, что у вас проблема в строках

 memory[0] = "Mem 0";

Они не копируют строку "Mem 0" в ваш массив памяти. Они заставляют память [i] указывать на строку.

Вам необходимо явно скопировать данные, используя strncpy

например. char s = "Mem 0"; strncpy (память 1 , с, макс (strlen (s) + 1, 29)) // max of 30 = (29 символов + '\ 0', поскольку это длина строки, которую вы выделили # определить это как константу

...