указатели — повреждение кучи, когда два байта превращаются в короткий. Переполнение стека

Я разрабатываю программу на C ++ и сталкиваюсь с этой ошибкой при запуске этого кода:

short readshort() {
short val=0;
(&val)[1]=data.front(); data.pop_front();
(&val)[0]=data.front(); data.pop_front();
return val;
}

Это ошибка, которую я получаю:

Run-Time Check Failure #2 - Stack around the variable 'val' was corrupted.

Теперь я должен упомянуть, что «данные» определяются с помощью std :: list data;

Я думаю, что знаю, в чем проблема, но я не могу придумать легкого решения. Я думаю, что эта ошибка вызвана тем, что «val» хранится в стеке, а не как указатель. Когда я пытаюсь получить доступ к указателю данных через «val», я получаю эту ошибку.

Решением, о котором я думал, было выделение «val» следующим образом:

short readshort() {
short* val=new short;
val[1]=data.front(); data.pop_front();
val[0]=data.front(); data.pop_front();
return *val;
}

Но я не вижу способа удалить «val», как только я его вернул, без необходимости каждый раз удалять его вне функции.
Есть ли способ сделать это в C ++ без утечки памяти? Я не видел, чтобы кто-нибудь разделял тип переменной (например, short) на байты, используя «(&val) [1] «раньше, и задавался вопросом, было ли это потому, что это породило ряд проблем, или это просто не известный метод?

Возвращаясь к реальному вопросу, как я могу сделать эти два байта короткими (или большими типами данных)? И есть ли лучший способ сделать это, чем то, что я пытался?

И последнее, я знаю, что в Java есть автоматический сборщик мусора, который автоматически устраняет утечки памяти. Предлагает ли C ++ такое же устройство? Я что-то слышал о Smart Pointers, но я не знаю, что они;)

1

Решение

Это безопасно и просто:

int16_t readshort()
{
union { int16_t s; char val[2]; } u;
u.val[1]=data.front(); data.pop_front();
u.val[0]=data.front(); data.pop_front();
return *(int16_t*)u.val;
}
2

Другие решения

Вам нужно навести указатель на символ *.

((char *)(&val))[1]=data.front();
((char *)(&val))[0]=data.front();

Думаю в твоем случае :(&Val) [1] = data.front (); Вы пишете данные для второго короткого. В результате вы получите ошибку.

1

(&val)[1]=data.front() ошибка, делая (&val)[1] вы пишете следующую ячейку памяти val это не определено.

(&val)[i] средства *(&val + i )
(&val)[0] средства *(&val + 0 ) знак равно *(&val) это хорошо
(&val)[1] средства *(&val + 1 ) = Но это ошибка, потому что ваша декларация short val так что мы можем получить доступ только к местоположению val.

+----+----+----+---+---+----+----+----+---+----+
|val      |        |
+----+----+----+---+---+----+----+----+---+---+----+
201   202  203 204 205 206  207   208 209 210  211
^           ^
|          |
&val         (&val + 1)
its not defined.

Вы могли бы использовать tyoecase как @Carl Norum предложил. Я просто пишу вторую форму, чтобы сделать это.

char *ptr = (char*)&val;

ptr[0]=data.front()
ptr[1]=data.front()

Но если вам нужно val как короткий и хотел получить доступ к отдельным байтам. Я хотел бы предложить union:

union Data{
short val;
char ch1;
char ch2;
};

union Data d;

d.ch1 = data.front()
d.ch2 = data.front()
1

(&val)[1] обращается к памяти, которую вы не распределили. Бам — неопределенное поведение. Оба ваших примера имеют одну и ту же проблему.

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

short readshort() {
short val=0;
((char *)&val)[1]=data.front(); data.pop_front();
((char *)&val)[0]=data.front(); data.pop_front();
return val;
}

Этот код действительно довольно уродливый, хотя. Почему не просто

short readshort() {
short val=0;
val  = data.front() << 8; data.pop_front();
val |= data.front() << 0; data.pop_front();
return val;
}

В зависимости от порядка байтов вам может понадобиться поменять местами 8 а также 0 там.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector