Как функция может вернуть cstring больше, чем массив символов, который она заполняет?

Я хочу начать и объяснить, что это просто любопытный вопрос, который поможет мне лучше понять C++.

Я работаю с библиотекой cstring на С++ для создания длинной cstring из нескольких переменных. Я запускал тестовую программу, чтобы увидеть, какой самый большой массив символов мне понадобится для хранения cstring. Для этого я определил buffer как глобальную переменную с размером, который, как я знал, будет содержать cstring. После его создания я использовал strlen, чтобы найти максимальную длину, которая составила 1517. Затем из любопытства, как это будет выглядеть в случае сбоя, я уменьшил размер buffer до 1000... и это все еще работало. У меня не было ошибки выполнения, пока я не уменьшил buffer до 300.

Когда я определил буфер в функции main(), я получаю сообщение об ошибке, когда buffer меньше вывода, но все равно печатает полный вывод. Я включаю свой рабочий пример, я использовал gbuffer и buffer для глобальной версии буфера и локальной версии буфера.

моя гипотеза заключается в том, что cstring записывается в память, а strcat продолжает записывать за пределы, установленные при определении буфера или gbuffer, а std::cout просто читает до тех пор, пока не достигнет нулевого символа, так что пока ничто другое не резервирует это пространство или не записывается там, программа по-прежнему работает, хотя нет никакой гарантии, что она будет работать, поскольку она записывает в память, не зарезервированную для нее.

#include <iostream>
#include <cstring>

//Global Variables
int Temperature=100;
int Heat=100;
int Cool=100;
char Status[100]="Nothing";
char Source[100]="Default";
char gbuffer[900];

struct schedulePoint {
  uint8_t days = 12;
  uint8_t heat = 65;
  uint8_t cool = 85;
  uint16_t start = 60*24;
  uint16_t end = 60*24;
};

struct myData {
  char myName[12] = "TestStat";
  schedulePoint schedule[64];
  char password[25];
  char ssid[25] = "Wifi Thermostat";
  bool hidden = false;
  uint8_t defaultHeat = 65;
  uint8_t defaultCool = 85;
  int timezone = 0;
  char serverUName[25] = "";
  char serverPW[25] = "";
} data;


char * get_JSON(char * buff, unsigned int buffSize) {
  std::cout << "Buffer Size:" << buffSize << "\n";
  char convert[500];
  strcpy(convert,"<script>schedule=[");
  strcpy(buff,convert);
  for (uint8_t z = 0; z < 64; z++) {
    if (z == 0) strcat(buff, "[");
    else strcat(buff, ",[");
    sprintf(convert, "%d,%d,%d,%d,%d]", data.schedule[z].days, data.schedule[z].heat, data.schedule[z].cool, data.schedule[z].start, data.schedule[z].end);
    strcat(buff, convert);
  }
  strcat(buff, "];\n");
  sprintf(convert, "SSID=\"%s\";\n",data.ssid);
  strcat(buff, convert);;
  strcat(buff, "states=[\"Off\",\"Heating\",\"Cooling\"];\n");
  sprintf(convert, "stats={\"Temperature\":%d,\"State\":%s,\"Heat\":%d,\"Cool\":%d,\"Source\":\"%s\"};\n</script>", Temperature, Status, Heat, Cool, Source);
  strcat(buff, convert);
  return buff;
}


int main(){
        char buffer[1000];
        std::cout << get_JSON(gbuffer,sizeof(gbuffer));
        std::cout << "\n";
        std::cout << "Ouput Size:" << (unsigned)strlen(gbuffer);
        std::cout << "\n";
        return 0;
}

person jeffpkamp    schedule 04.01.2021    source источник
comment
C++ похож на боулинг без дорожных бамперов. Ничто не помешает вам писать за пределами массива. И хуже всего то, что программа все еще может работать. Но, в конце концов, Undefined Behavior не определено.   -  person scohe001    schedule 04.01.2021


Ответы (1)


моя гипотеза заключается в том, что cstring записывается в память, а strcat продолжает записывать за пределы, установленные при определении буфера или gbuffer, а std::cout просто читает до тех пор, пока не достигнет нулевого символа, так что пока ничто другое не резервирует это пространство или написанное там, программа все еще работает, хотя нет гарантии, что она будет работать, так как она пишет в не отведенной для нее памяти.

Верный.

Поведение вашей программы не определено.

Не делай этого.

person Asteroids With Wings    schedule 04.01.2021