Я разрабатываю программу на 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, но я не знаю, что они;)
Это безопасно и просто:
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;
}
Вам нужно навести указатель на символ *.
((char *)(&val))[1]=data.front();
((char *)(&val))[0]=data.front();
Думаю в твоем случае :(&Val) [1] = data.front (); Вы пишете данные для второго короткого. В результате вы получите ошибку.
(&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()
(&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
там.