Есть ли причина, по которой указатель кучи не будет назначен массиву? - PullRequest
1 голос
/ 03 ноября 2019

Структура узла следующая:

struct Node {
    int data;
    Node *next;
    bool someBool;
};

У меня есть следующая пара строк:

    Node *hello = new Node{data, cur, !new_head}; // line A
    array[new_head_index] = hello;                // line B
}                                                 // line C

Значение new_head_index подтверждается как 1 GDB навсе 3 строки.

GDB подтверждает, что в строках A, B и C, когда я делаю p *hello (выведите содержимое hello), я получаю:

(gdb) p *hello
$7 = {data = 888, next = 0x8414e70, someBool = false}

Но печать содержимого array@2 (массив имеет длину 2, объявленная в main как Node *heads[numHeads] = {new Node{0, nullptr, false}, nullptr};) имеет это в строках B и C (до фактического выполнения строки):

(gdb) p **array@2
$8 = {{data = 777, next = 0x8414e70, someBool = true}, {data = 33, next = 0x378, someBool = 112}}

(узел 777ожидается, я заполнил это раньше).

Находясь в строке A, он имеет:

(gdb) p **array@2
$9 = {{data = 777, next = 0x8414e70, someBool = true}, {data = 61265, next = 0x0, someBool = false}}

По существу, hello не присваивается array[1]. Что может быть причиной этого?

Вот минимальный воспроизводимый пример: main.cc

#include <iostream>
#include <string>
#include "new_mod.h"
using namespace std;

int len(Node **array) {
    int i = 0, count = 0;
    while (array[i++]) { ++count; }
    return count;
}

void attach(Node **array, int head, int index, int data) {
    Node *hello = new Node{data, cur};
    array[new_head_index] = hello;
}

int main() {
    string command;
    int head;
    Node *array[numHeads] = {new Node{0, nullptr}, nullptr};

    while (cin >> command) {
        if (command == "a") {
            int m, x;
            cin >> head >> m >> x;

            attach(array, head, m, x);
        }
    }

}

mod.h

#ifndef MOD_H
#define MOD_H
#include <ostream>

struct Node {
    int data;
    Node *next;
    bool someBool = false;
};

const int numHeads = 2;

void attach(Node **array, int head, int index, int data);
#endif

Попробуйте вставить этоinput (я назвал этот файл a.in)

a 0 0 777
a 0 1 888

Скомпилируйте с g++ -Wall -g main.cc -o newe, чтобы вы могли что-то делать с GDB!

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

gdb newe
b attach(Node**, int, int, int)
run <a.in
layout n
c
n
n
n
n
n
n
n          (comment: I did n until line Node *hello = new Node{data, cur};)
p **array@2
n
n
p **array@2 (the problem is shown)

1 Ответ

0 голосов
/ 03 ноября 2019

Проблема в том, что Node *array[2] и Node **array являются не одним и тем же, и когда вы запрашиваете GDB p **array@2, вы просите интерпретировать массив, как если бы array был двойнымуказатель, а не массив.

Вы можете наблюдать это перед началом цикла ввода:

(gdb) p *array@2
$1 = {0x55555556ae70, 0x0}
(gdb) p *array[0]
$2 = {data = 0, next = 0x0, someBool = false}

Здесь вы можете видеть, что array находится в ожидаемом состоянии: первый узел - все нуливторая - NULL.

Но если вы сделаете:

(gdb) p **array@2
$3 = {{data = 0, next = 0x0, someBool = false}, {data = 4113, next = 0x3737203020302061, someBool = 55}}

, вы сразу увидите, что не смотрите на нужные данные: вы знаете , что array[1] равно NULL, поэтому не может указывать на Node с 4113 в нем.

Я не верю, что существует встроенный синтаксис GDB для print *array[0 .. N]. Одним из возможных решений является определение вспомогательной функции (которая может быть легко обобщена для принятия имени и размера массива в качестве параметров, но для простоты здесь используется тривиально):

(gdb) def parray
Type commands for definition of "parray".
End with a line saying just "end".
>print *array[0]
>print *array[1]
>end
(gdb) parray
$4 = {data = 0, next = 0x0, someBool = false}
Cannot access memory at address 0x0
(gdb) c
Continuing.

Breakpoint 1, attach (array=0x7fffffffdb70, head=0, index=1, data=888) at foo.cc:34
34          array[new_head_index] = hello;
(gdb) n
35      }
(gdb) parray
$5 = {data = 777, next = 0x55555556ae70, someBool = false}
$6 = {data = 888, next = 0x55555556ae70, someBool = false}
...