2016-05-28 4 views
-4

Следующий фрагмент кода выполняется на 64-битном Ubuntu 14.04, в то время как он дает ошибку seg в 32-битном Ubuntu 14.04. GCC версии того же как в 4.8.4 (Ubuntu 4.8.4-2ubuntu1 ~ 14,04)Разница в поведении между 32 бит и 64 бит

#include<stdio.h> 
main() 

{ 

    int* a; 
    int* b; 
    *a = 40; 
    b=a; 
    printf ("%x ............. %p ...........%d \n",*a,a, *a); 
} 

То же самое работает на 32-битной системе, если один из двух сделали -

  1. Закомментируйте b = a
  2. Добавить a=malloc (sizeof(int)); до * a = 40;

Может кто-то пожалуйста, объясните это наблюдение

+5

Исходный код имеет неопределенное поведение. Вы не присваиваете действительный адрес памяти 'a', поэтому он имеет случайный адрес. Разыменовывая это, чтобы назначить 40 записей в случайную память, чтобы все могло случиться. Ошибка 'malloc' исправляет ошибку, но тогда у вас есть адрес памяти, если вы не называете' free (a) '. Присвоение 'a'' b' не изменяет никакого такого поведения. –

+2

Включить предупреждения компилятора: * warning C4700: неинициализированная локальная переменная 'a' используется * –

+0

Если вы не добавляете ** 2 **, это * неопределенное поведение *, потому что вы пытаетесь записать в нераспределенную память. ** 1 ** ничего не меняет, потому что вы не используете 'b' нигде. – Haris

ответ

2

Это не вопрос 32-бит против 64-бит, но вопрос об использовании указателей, не указывающих на действительный адрес памяти. В фрагменте кода вы указали указатели *a и *b, фактически не указывая их нигде, что приводит к неопределенному поведению.

При использовании указателей всегда выделяйте сразу необходимую память или указывайте их на существующую соответствующую переменную.

Например, все последующие утверждения:

int *a = NULL; 
int *b = malloc(sizeof(int)); 
int c = 42; 
int *d = &c; 

К их не инициализируется, они указывают на произвольное место. *a = 40;, вероятно, работал «случайно» для вас, поскольку он мог указывать на пространство памяти, в котором у вас был доступ в то время. Но в общем случае этот фрагмент должен приводить к сбою segmetation в любой операционной системе.

Если вы не планируете указывать указатель сразу на действительный адрес памяти, рассмотрим его инициализации в NULL, чтобы избежать иметь оборванных указатель. Вы никогда не должны разыскивать указатель NULL, но вы всегда можете проверить, есть ли указатель NULL, прежде чем пытаться это сделать. Например:

int *a = NULL; 
if (a != NULL) { 
    *a = 42; 
} 
int *b = a; 
if (b != NULL) { 
    printf("%d\n", *b); 
} 

Этот фрагмент кода не будет печатать ничего, и как *a и *b будет NULL, но ваш код не будет производить ошибку сегментации.

Для того, что стоит, я также получил ошибку сегментации на 64-разрядной системе Debian.

[редактировать интегрировать @ Муравьев, @ tuple_cat-х и обратные связи @Weather лопастных в]

+3

Я не вижу, как это имеет какое-либо отношение к * динамической * памяти. Вы могли бы просто выполнить 'int c; int * a = & c; 'и таким образом получить действительные' a' и '* a'. Здесь нет необходимости включать * динамическую * память. Понятие «указатель» никак не связано с динамической памятью. – AnT

+3

Кроме того, 'malloc' возвращает' void * '. Кастинг, который [не нужен] (http://stackoverflow.com/q/605845/3425536). – emlai

+0

@AnT Спасибо за отзывы, я включил его, чтобы сделать ответ более общим: при использовании указателей они должны указывать где-то действительное. – Adama