2015-11-17 4 views
0
#include <iostream> 
#include <string> 
using namespace std; 

struct Bar { 
    string str; 
}; 

struct Foo { 
    Bar* bar; 
};  

int main() { 
    Foo foo; 
    if (true) { 
     Bar bar; 
     bar.str = "test"; 
     foo.bar = &bar; // version 1 
     // *(foo.bar) = bar; // version 2 
    } 
    cout << foo.bar->str << endl; 
    return 0; 
} 

Вышеупомянутая программа ничего не печатает. Я понимаю, что когда оператор if выходит, переменная строка, которая была выделена в стеке, больше не существует, а foo.bar содержит указатель на неопределенное расположение памяти в стеке. Я не понимаю, что когда я меняю строку на текущую прокомментированную строку (отмеченную версией 2). Это дает мне ошибку сегментации. Может ли кто-нибудь помочь мне понять, почему это так? Кроме того, если я хочу напечатать «тест» для этой программы, какие изменения кода я должен сделать?переменная область действия и указатель

ответ

1

Когда вы строите Foo с помощью

Foo foo; 

член foo.bar не инициализирован. Разделение неинициализированного указателя является причиной неопределенного поведения. В вашем случае неопределенное поведение проявляется как ошибка сегментации.

Кроме того, если я хочу напечатать «тест» для этой программы, какие изменения кода я должен сделать?

  1. Выделяем память для foo.bar.
  2. Назначить bar до *(foo.bar) после выделения памяти.
  3. Обязательно освободите память до завершения функции.
int main() { 
    Foo foo; 
    if (true) { 
     Bar bar; 
     bar.str = "test"; 
     foo.bar = new std::string; 
     *(foo.bar) = bar; 
    } 
    cout << foo.bar->str << endl; 
    delete foo.bar; 
    return 0; 
} 
+0

Но почему int * a; * А = 1; работает? из-за примитивного типа? – pippo

+0

@pippo, это также является причиной неопределенного поведения. –

+0

Нет, int * a; * А = 1; так же плохо. Однако возможно, что случайно вы нашли действительный адрес памяти. – Marandil

0

2). Это дает мне ошибку сегментации. Может ли кто-нибудь помочь мне понять, почему это так?

Для *(foo.bar) = bar;, вы пытаетесь разыменования указателя, который вы не выделять для него память, т.е. dangling pointer. Это будет undifined behaviour.

Кроме того, если я хочу напечатать «тест» для этой программы, какие изменения кода я должен сделать?

Выделите память, прежде чем разыгрывать ее.

foo.bar = new Bar; 
*(foo.bar) = bar; 

Не забудьте его окончательно удалить.

+0

tks для этих ссылок! – pippo

0

Heyy,
У вас возникла проблема с кодом. Утверждение cout в последнем, которое должно было напечатать Test, было вне области if. Ниже приведен полностью функциональный код.
Он отлично работает

#include <iostream> 
#include <string> 
using namespace std; 

struct Bar { 
    string str; 
}; 

struct Foo { 
    Bar* bar; 
};  

int main() { 
    Foo foo; 
    if (true) { 
     Bar bar; 
     bar.str = "test"; 
     foo.bar = &bar; // version 1 
     // *(foo.bar) = bar; // version 2 
    //previously bracets were here which made bar out of the scope due to 
    //which str wasn't accessible. 
    cout << (foo.bar->str) << endl;//you had a problem in the scope} 
    return 0; 
} 
+0

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

+0

Я собирался иметь закрывающие скобки, где находится в моей программе, поэтому я могу проверить, могу ли я получить доступ к foo.bar-> str. Я понимаю, что ваши изменения заставят код работать. ТКС. – pippo

+0

O действительно !! Это хорошо, брат. Тогда вы должны знать, почему вы получаете ошибку сегментации? –

Смежные вопросы