That's agood point. data = buffer; assumes buffer is a null terminated sequence. But as you're reading a binary block that could contain zeros, you should do data.assign(buffer, lSize); However, that won't cause the crash.
I stand by my earlier advice; earlier heap corruption.
Content-wise there seems to be no difference between buffer and data (assuming you meant to compare them after the fread operation).
However if I use malloc, data ends up to be larger than the size I specified for allocation (lSize+1), to be exact lSize+1 = 1104 bytes while data.size() = 1112 bytes.
I'm not sure though if its not the same case with calloc since std::string data = buffer only copies the data up to the first 0 char (if I understood this correctly) and since calloc fills the allocated memory with 0 char's then the string would be the same size as buffer.
And yeah there is a reason I'm doing it this way but thats not the point of discussion here.
The reason data is larger with malloc than with calloc is because the buffer doesn't have any zeros.
calloc intialises the buffer with zeros, and since you read one less than the size of the buffer, it's always null terminated. But malloc doesn't touch the buffer, so the last character is random and clearly not zero.
As you're doing
data = buffer;
it's reading past the end of the buffer. So, I repeat, you should be using