В общем столкнулся с таким непонятным багом. Есть функция, которая упаковывает исходное сообщение в некий пакет. Для этого она находит длину исходного сообщения. и вот тут то вызывается strlen(message);
. message - const char* из аргумента функции. до вызова strlen это обычная строка, после вызова однако она коверкается до неузнаваемости. Собирал g++ и clang++ оба с -O0 -g. однако повторить в минимальном варианте вне кода самой программы не получается.
Что тут вообще может случиться, что меняется строковый литерал?
это вызывается из конструктора одного класса:
{
const char* reuest = scom::create_auth_request("User");
socket->send(request);
}
const char* scom::create_auth_request(const char* name)
{
const char* result;
int len;
len = strlen(name);
char buff[1 + len];
sprintf(buff, "%01d%s", AUTH_REQUEST, name); /* AUTH_REQUEST = 0 */
result = buff;
return result;
}
void scom::ClientSocket::send(int connection, const char* message)
{
unsigned int total = 0;
/* здесь message = "0User" */
unsigned int len = strlen(message);
/* здесь message уже "h\364\n\br" */
/* остальное уже в принципе не важно */
/*
if(len > 1024)
throw scom::Exception();
unsigned int bytesleft = len + 2;
unsigned int n;
char to_send[len + 2];
memset(to_send, 0, len + 2);
uint16_t nlen = htons(len);
to_send[0] = nlen>>8;
to_send[1] = nlen;
strcpy(to_send+2, message);
while(total < len + 2)
{
n = ::send(connection, to_send+total, bytesleft, 0);
if(n == -1)
break;
total += n;
bytesleft -= n;
}
if(n == -1)
throw scom::Send();
}
*/
посмотрел на scom::create_auth_request
- там возвращается указатель на локальный буфер. По выходу с функции он конечно в памяти остается и даже данные по нему живые, но когда вызывается следующая функция, она перетирает стек своими переменными - она же не знает о том, что там остались данные. Это абсолютно совпадает с наблюдаемым поведением. В Вашем случае этот буфер перетирает собственно strlen
.
Как можно ещё проверить, что это именно так. Перепишите функцию отправки так
void scom::ClientSocket::send(int connection, const char* message)
{
int i = 0;
int j = 0;
int z = 0;
unsigned int total = 0;
/* здесь message = "0User" */
нужно именно как минимум 8 байт, потому что в create_auth_request буфер находиться как минимум с 9 байта. Но компилятор может это дело все переставить.
Как это пофиксить. Первый способ - передать буфер buff
как параметр функции и хранить его вызывающей программе. Второй способ - выделить память явно через malloc. Третий способ - писать все таки на с++ и использовать std::string
вместо char*
.
B.T.W. - Вы похоже используете VLA - а это gcc специфик.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Есть код на С++ в нём используются std::vector и std::mapМне нужно перенести код на язык СИ где нет STL, делать реализацию методов из STL vector и map для массива...
Допустим у меня есть модуль/класс: TGAImage, а внутри него функция: