I have a application that I need to scan for certain datatypes in the memory. To get some benchmarking tests, I whipped up this program :
long count = 0;
MEMORY_BASIC_INFORMATION meminfo;
unsigned char *addr = 0;
HANDLE hProc = GetCurrentProcess();
while (true){
if ( VirtualQueryEx( hProc, addr, &meminfo, sizeof( meminfo ) ) == 0 ){
break;
}
if ( ( meminfo.State & MEM_COMMIT ) && ( meminfo.Protect & WRITABLE ) ){
addr = (unsigned char*)meminfo.BaseAddress + meminfo.RegionSize;
count++;
printf("%d",count);
}
}
printf("%ld\n",count);
This program doesn't work, it blocks/crashes at the first memory chunk. And conceptually it fails too, ideally I need pointers to all of the variables in the current process, so I can check if they're of any relevance to me. I've google'd around for a while now to no avail, if someone could push me in the right direction that'd be great.
I know it's generally a bad idea to do this in the first place, I'd just like to know how it'd be done if I needed to do it.
WRITEABLE (at the second if block) is not one of the memory protection constants. Did you mean PAGE_READWRITE? You can find the full list of options here.
Memory access permissions are tricky. The rest of the function works though. This works, though one can view addr only when stepping through:
#include <Windows.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
long count = 0;
MEMORY_BASIC_INFORMATION meminfo;
unsigned char *addr = 0;
HANDLE hProc = GetCurrentProcess();
while (true)
{
if (VirtualQueryEx(hProc, addr, &meminfo, sizeof(meminfo)) == 0)
{
// TODO GetLastError
break;
}
// if ((meminfo.State & MEM_COMMIT) && (meminfo.Protect & PAGE_READWRITE))
{
addr = (unsigned char*) meminfo.BaseAddress + meminfo.RegionSize;
count++;
printf("%d", count);
}
}
printf("%ld\n", count);
}
Related
I have enumerated a processes modules and have a MODULEINFO. From that I have a base address, size of the module, and the entrypoint. If I have a separate process with an integer int x = 4 defined in main(), can I scan for that integer's address using what I have with MODULEINFO? Wouldn't x exist on the stack, which is separate from the module exe?
I tried making a loop with the base address and SizeOfImage member, casting the base address to a byte*, and then adding 1 byte and then casting it to a int* to search for a specific value, however every value I got back was a "0". I believe my method was (grossly) incorrect.
If it is possible to scan an int value can anyone point me in the general direction to do so?
Yes--local variables (non-static ones, anyway) are allocated on the stack. To see their values, you'll need to write something on the order of a debugger, such as pausing the program while it's running (and the function containing the variable of interest is active), and walk the stack to find the value.
Since you're apparently using Windows, functions you'll probably want to look at include:
WaitForDebugEvent (or WaitForDebugEventEx)
ContinueDebugEvent
Stackwalk64
You'll probably also want to look at the dbghlp API, probably starting with these:
SymInitialize
SymFromName
SymCleanup
There's a lot more there to consider, but that's probably enough to at least get a bit of a start. I previously posted an answer that demonstrates StackWalk64, and some of the Sym* stuff.
Here's some code with the bare skeleton of a debugger that will spawn a child process, and then log the debug events it produces:
#include <windows.h>
#include <stdio.h>
#include "child_process.h"
void dispatch_child_event(DEBUG_EVENT const &event, child_process const &child) {
char *file_name;
char buffer[512];
switch ( event.dwDebugEventCode ) {
case LOAD_DLL_DEBUG_EVENT:
file_name = child.get_string(event.u.LoadDll.lpImageName);
if ( event.u.LoadDll.fUnicode)
printf("Loading %S\n", (wchar_t *)file_name);
else
printf("Loading %s\n", file_name);
break;
case EXCEPTION_DEBUG_EVENT:
switch (event.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
{
if ( event.u.Exception.dwFirstChance)
break;
EXCEPTION_RECORD const &r = event.u.Exception.ExceptionRecord;
printf("Access Violation %x at %0#p\n",
r.ExceptionCode,
r.ExceptionAddress);
break;
}
case EXCEPTION_BREAKPOINT:
printf("Breakpoint reached\n");
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
if ( !event.u.Exception.dwFirstChance)
printf("Misaligned data exception.\n");
break;
case EXCEPTION_SINGLE_STEP:
printf("Single Step...\n");
break;
case DBG_CONTROL_C:
if ( !event.u.Exception.dwFirstChance)
printf("Control+C pressed\n");
break;
break;
}
case CREATE_THREAD_DEBUG_EVENT:
printf("Client created a thread\n");
break;
case CREATE_PROCESS_DEBUG_EVENT:
printf("Create-Process\n");
break;
case EXIT_THREAD_DEBUG_EVENT:
printf("Thread exited.\n");
break;
case UNLOAD_DLL_DEBUG_EVENT:
printf("DLL being unloaded\n");
break;
case OUTPUT_DEBUG_STRING_EVENT: {
OUTPUT_DEBUG_STRING_INFO const &d = event.u.DebugString;
char *string = child.get_debug_string(d.lpDebugStringData,
d.nDebugStringLength);
if ( d.fUnicode)
printf("Debug string: %S\n", string);
else
printf("Debug string: %s\n", string);
break;
}
}
}
int main(int argc, char **argv) {
DEBUG_EVENT event;
if ( argc < 2 ) {
fprintf(stderr, "Usage: Trace [executable|PID]");
return EXIT_FAILURE;
}
child_process child(argv[1]);
do {
WaitForDebugEvent(&event, INFINITE);
dispatch_child_event(event, child);
ContinueDebugEvent( event.dwProcessId,
event.dwThreadId,
DBG_CONTINUE );
} while ( event.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
return 0;
}
That uses the following child_process header:
#ifndef CHILD_PROCESS_H_INC_
#define CHILD_PROCESS_H_INC_
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <io.h>
#include "syserror.h"
struct no_spawn {
no_spawn() { system_error("Spawning Program"); }
};
class child_process {
HANDLE process_;
HANDLE thread_;
mutable char buffer[FILENAME_MAX];
public:
child_process(char const *filename);
char *get_string(void *string_name, DWORD num = 0) const;
char *get_debug_string(void *string, DWORD num) const;
HANDLE process() { return process_; }
HANDLE thread() { return thread_; }
~child_process() { CloseHandle(process()); }
};
#endif
The implementation of that class is as follows:
#include "child_process.h"
static BOOL find_image(char const *name, char *buffer) {
// Try to find an image file named by the user.
// First search for the exact file name in the current
// directory. If that's not found, look for same base name
// with ".com", ".exe" and ".bat" appended, in that order.
// If we can't find it in the current directory, repeat
// the entire process on directories specified in the
// PATH environment variable.
//
#define elements(array) (sizeof(array)/sizeof(array[0]))
static char *extensions[] = {".com", ".exe", ".bat", ".cmd"};
int i;
char temp[FILENAME_MAX];
if (-1 != _access(name, 0)) {
strcpy(buffer, name);
return TRUE;
}
for (i=0; i<elements(extensions); i++) {
strcpy(temp, name);
strcat(temp, extensions[i]);
if ( -1 != _access(temp, 0)) {
strcpy(buffer, temp);
return TRUE;
}
}
_searchenv(name, "PATH", buffer);
if ( buffer[0] != '\0')
return TRUE;
for ( i=0; i<elements(extensions); i++) {
strcpy(temp, name);
strcat(temp, extensions[i]);
_searchenv(temp, "PATH", buffer);
if ( buffer[0] != '\0')
return TRUE;
}
return FALSE;
}
child_process::child_process(char const *filename) {
if (isdigit(filename[0])) {
DWORD id = atoi(filename);
process_ = OpenProcess(PROCESS_ALL_ACCESS, false, atoi(filename));
DebugActiveProcess(id);
}
else {
char buf[FILENAME_MAX];
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(si);
if (!find_image(filename, buf))
throw no_spawn();
BOOL new_process_ = CreateProcess(buf, NULL, NULL, NULL, FALSE,
DEBUG_ONLY_THIS_PROCESS,
NULL, NULL,
&si, &pi);
if (!new_process_)
throw no_spawn();
CloseHandle(pi.hThread);
process_ = pi.hProcess;
thread_ = pi.hThread;
}
}
char *child_process::get_string(void *string_name, DWORD num) const {
// string_name is a pointer to a pointer to a string, with the pointer and the
// string itself located in another process_. We use Readprocess_Memory to read
// the first pointer, then the string itself into our process_ address space.
// We then return a pointer (in our address space) to the string we read in.
//
char *ptr;
SIZE_T bytes_read;
if ( 0 == num )
num = sizeof(buffer);
if ( string_name == NULL )
return NULL;
ReadProcessMemory(process_,
string_name,
&ptr,
sizeof(ptr),
&bytes_read);
if (NULL == ptr )
return NULL;
ReadProcessMemory(process_,
ptr,
buffer,
num,
&bytes_read);
return buffer;
}
char *child_process::get_debug_string(void *string, DWORD num) const {
static char buffer[FILENAME_MAX];
SIZE_T bytes_read;
if ( string == NULL )
return NULL;
ReadProcessMemory(process_,
string,
buffer,
num,
&bytes_read);
return buffer;
}
That's not enough to do everything you want yet, but at least it should give you a start in the general direction.
Oh, one disclaimer: I wrote most of this code quite a long time ago. There are parts I'd certainly do differently if I were to write it today.
I am trying to develop a little application in C++, within a Linux environment, which does the following:
1) gets a data stream (a series of arrays of doubles) from the output of a 'black-box' and writes it to a pipe. The black-box can be thought as an ADC;
2) reads the data stream from the pipe and feeds it to another application which requires these data as stdin;
Unfortunately, I was not able to find tutorials or examples. The best way I found to realize this is summarized in the following test-bench example:
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#define FIFO "/tmp/data"
using namespace std;
int main() {
int fd;
int res = mkfifo(FIFO,0777);
float *writer = new float[10];
float *buffer = new float[10];
if( res == 0 ) {
cout<<"FIFO created"<<endl;
int fres = fork();
if( fres == -1 ) {
// throw an error
}
if( fres == 0 )
{
fd = open(FIFO, O_WRONLY);
int idx = 1;
while( idx <= 10) {
for(int i=0; i<10; i++) writer[i]=1*idx;
write(fd, writer, sizeof(writer)*10);
}
close(fd);
}
else
{
fd = open(FIFO, O_RDONLY);
while(1) {
read(fd, buffer, sizeof(buffer)*10);
for(int i=0; i<10; i++) printf("buf: %f",buffer[i]);
cout<<"\n"<<endl;
}
close(fd);
}
}
delete[] writer;
delete[] buffer;
}
The problem is that, by running this example, I do not get a printout of all the 10 arrays I am feeding to the pipe, whereas I keep getting always the first array (filled by 1).
Any suggestion/correction/reference is very welcome to make it work and learn more about the behavior of pipes.
EDIT:
Sorry guys! I found a very trivial error in my code: in the while loop within the writer part, I am not incrementing the index idx......once I correct it, I get the printout of all the arrays.
But now I am facing another problem: when using a lot of large arrays, these are randomly printed out (the whole sequence is not printed); as if the reader part is not able to cope with the speed of the writer. Here is the new sample code:
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#define FIFO "/tmp/data"
using namespace std;
int main(int argc, char** argv) {
int fd;
int res = mkfifo(FIFO,0777);
int N(1000);
float writer[N];
float buffer[N];
if( res == 0 ) {
cout<<"FIFO created"<<endl;
int fres = fork();
if( fres == -1 ) {
// throw an error
}
if( fres == 0 )
{
fd = open(FIFO, O_WRONLY | O_NONBLOCK);
int idx = 1;
while( idx <= 1000 ) {
for(int i=0; i<N; i++) writer[i]=1*idx;
write(fd, &writer, sizeof(float)*N);
idx++;
}
close(fd);
unlink(FIFO);
}
else
{
fd = open(FIFO, O_RDONLY);
while(1) {
int res = read(fd, &buffer, sizeof(float)*N);
if( res == 0 ) break;
for(int i=0; i<N; i++) printf(" buf: %f",buffer[i]);
cout<<"\n"<<endl;
}
close(fd);
}
}
}
Is there some mechanism to implement in order to make the write() wait until read() is still reading data from the fifo, or am I missing something trivial also in this case?
Thank you for those who have already given answers to the previous version of my question, I have implemented the suggestions.
The arguments to read and write are incorrect. Correct ones:
write(fd, writer, 10 * sizeof *writer);
read(fd, buffer, 10 * sizeof *buffer);
Also, these functions may do partial reads/writes, so that the code needs to check the return values to determine whether the operation must be continued.
Not sure why while( idx <= 10) loop in the writer, this loop never ends. Even on a 5GHz CPU. Same comment for the reader.
Currently I'm using this function which I've cobbled together from reading several loosely related questions all over the internet. The problem I'm having is that the first time I ran it it returned an error, but unfortunately I haven't been able to reproduce it. Now when I run it it simply returns 0 every time.
DWORD GetAddressOfString(char *input)
{
unsigned char *p = NULL;
MEMORY_BASIC_INFORMATION info;
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, _processID);
for (p = NULL; VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info); p += info.RegionSize)
{
if (info.State == MEM_COMMIT && (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
{
char *buffer = new char[info.RegionSize];
SIZE_T bytesRead;
ReadProcessMemory(process, p, &buffer, info.RegionSize, &bytesRead);
for (int i = 0; i <= (info.RegionSize - sizeof(input)); i++)
{
if (memcmp(input, &buffer[i], sizeof(input)) == 0)
{
return i;
}
}
}
}
}
Here's a quick and dirty version that searches for data in itself. If you open up Notepad++, type "SomeDataToFind", replace the pid with the correct value, and run it, it should find the data as well. It might give you something to start with and embellish to suit your needs.
Your code was searching for the wrong length, returning the wrong offset, leaking memory like a sieve, and not always returning a value which is undefined behavior.
#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
char* GetAddressOfData(DWORD pid, const char *data, size_t len)
{
HANDLE process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
if(process)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
MEMORY_BASIC_INFORMATION info;
std::vector<char> chunk;
char* p = 0;
while(p < si.lpMaximumApplicationAddress)
{
if(VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info))
{
p = (char*)info.BaseAddress;
chunk.resize(info.RegionSize);
SIZE_T bytesRead;
if(ReadProcessMemory(process, p, &chunk[0], info.RegionSize, &bytesRead))
{
for(size_t i = 0; i < (bytesRead - len); ++i)
{
if(memcmp(data, &chunk[i], len) == 0)
{
return (char*)p + i;
}
}
}
p += info.RegionSize;
}
}
}
return 0;
}
int main()
{
const char someData[] = "SomeDataToFind";
std::cout << "Local data address: " << (void*)someData << "\n";
//Pass whatever process id you like here instead.
DWORD pid = GetCurrentProcessId();
char* ret = GetAddressOfData(pid, someData, sizeof(someData));
if(ret)
{
std::cout << "Found: " << (void*)ret << "\n";
}
else
{
std::cout << "Not found\n";
}
return 0;
}
Using the readlink function used as a solution to How do I find the location of the executable in C?, how would I get the path into a char array? Also, what do the variables buf and bufsize represent and how do I initialize them?
EDIT: I am trying to get the path of the currently running program, just like the question linked above. The answer to that question said to use readlink("proc/self/exe"). I do not know how to implement that into my program. I tried:
char buf[1024];
string var = readlink("/proc/self/exe", buf, bufsize);
This is obviously incorrect.
This Use the readlink() function properly for the correct uses of the readlink function.
If you have your path in a std::string, you could do something like this:
#include <unistd.h>
#include <limits.h>
std::string do_readlink(std::string const& path) {
char buff[PATH_MAX];
ssize_t len = ::readlink(path.c_str(), buff, sizeof(buff)-1);
if (len != -1) {
buff[len] = '\0';
return std::string(buff);
}
/* handle error condition */
}
If you're only after a fixed path:
std::string get_selfpath() {
char buff[PATH_MAX];
ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
if (len != -1) {
buff[len] = '\0';
return std::string(buff);
}
/* handle error condition */
}
To use it:
int main()
{
std::string selfpath = get_selfpath();
std::cout << selfpath << std::endl;
return 0;
}
Accepted answer is almost correct, except you can't rely on PATH_MAX because it is
not guaranteed to be defined per POSIX if the system does not have such
limit.
(From readlink(2) manpage)
Also, when it's defined it doesn't always represent the "true" limit. (See http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html )
The readlink's manpage also give a way to do that on symlink :
Using a statically sized buffer might not provide enough room for the
symbolic link contents. The required size for the buffer can be
obtained from the stat.st_size value returned by a call to lstat(2) on
the link. However, the number of bytes written by readlink() and read‐
linkat() should be checked to make sure that the size of the symbolic
link did not increase between the calls.
However in the case of /proc/self/exe/ as for most of /proc files, stat.st_size would be 0. The only remaining solution I see is to resize buffer while it doesn't fit.
I suggest the use of vector<char> as follow for this purpose:
std::string get_selfpath()
{
std::vector<char> buf(400);
ssize_t len;
do
{
buf.resize(buf.size() + 100);
len = ::readlink("/proc/self/exe", &(buf[0]), buf.size());
} while (buf.size() == len);
if (len > 0)
{
buf[len] = '\0';
return (std::string(&(buf[0])));
}
/* handle error */
return "";
}
Let's look at what the manpage says:
readlink() places the contents of the symbolic link path in the buffer
buf, which has size bufsiz. readlink does not append a NUL character to
buf.
OK. Should be simple enough. Given your buffer of 1024 chars:
char buf[1024];
/* The manpage says it won't null terminate. Let's zero the buffer. */
memset(buf, 0, sizeof(buf));
/* Note we use sizeof(buf)-1 since we may need an extra char for NUL. */
if (readlink("/proc/self/exe", buf, sizeof(buf)-1) < 0)
{
/* There was an error... Perhaps the path does not exist
* or the buffer is not big enough. errno has the details. */
perror("readlink");
return -1;
}
char *
readlink_malloc (const char *filename)
{
int size = 100;
char *buffer = NULL;
while (1)
{
buffer = (char *) xrealloc (buffer, size);
int nchars = readlink (filename, buffer, size);
if (nchars < 0)
{
free (buffer);
return NULL;
}
if (nchars < size)
return buffer;
size *= 2;
}
}
Taken from: http://www.delorie.com/gnu/docs/glibc/libc_279.html
#include <stdlib.h>
#include <unistd.h>
static char *exename(void)
{
char *buf;
char *newbuf;
size_t cap;
ssize_t len;
buf = NULL;
for (cap = 64; cap <= 16384; cap *= 2) {
newbuf = realloc(buf, cap);
if (newbuf == NULL) {
break;
}
buf = newbuf;
len = readlink("/proc/self/exe", buf, cap);
if (len < 0) {
break;
}
if ((size_t)len < cap) {
buf[len] = 0;
return buf;
}
}
free(buf);
return NULL;
}
#include <stdio.h>
int main(void)
{
char *e = exename();
printf("%s\n", e ? e : "unknown");
free(e);
return 0;
}
This uses the traditional "when you don't know the right buffer size, reallocate increasing powers of two" trick. We assume that allocating less than 64 bytes for a pathname is not worth the effort. We also assume that an executable pathname as long as 16384 (2**14) bytes has to indicate some kind of anomaly in how the program was installed, and it's not useful to know the pathname as we'll soon encounter bigger problems to worry about.
There is no need to bother with constants like PATH_MAX. Reserving so much memory is overkill for almost all pathnames, and as noted in another answer, it's not guaranteed to be the actual upper limit anyway. For this application, we can pick a common-sense upper limit such as 16384. Even for applications with no common-sense upper limit, reallocating increasing powers of two is a good approach. You only need log n calls for a n-byte result, and the amount of memory capacity you waste is proportional to the length of the result. It also avoids race conditions where the length of the string changes between the realloc() and the readlink().
I have written a read function which reads values from serial port(LINUX) . It returns values as pointer to char . I am calling this function in another function and storing it again in a variable as pointer to char . I occasionally got stack over flow problem and not sure if this function is creating problem.
The sample is provided below. Please give some suggestions or criticism .
char *ReadToSerialPort( )
{
const int buffer_size = 1024;
char *buffer = (char *)malloc(buffer_size);
char *bufptr = buffer;
size_t iIn;
int iMax = buffer+buffer_size-bufptr;
if ( fd < 1 )
{
printf( "port is not open\n" );
// return -1;
}
iIn = read( fd, bufptr, iMax-1 );
if ( iIn < 0 )
{
if ( errno == EAGAIN )
{
printf( "The errror in READ" );
return 0; // assume that command generated no response
}
else
printf( "read error %d %s\n", errno, strerror(errno) );
}
else
{
// *bufptr = '\0';
bufptr[(int)iIn<iMax?iIn:iMax] = '\0';
if(bufptr != buffer)
return bufptr;
}
free(buffer);
return 0;
} // end ReadAdrPort
int ParseFunction(void)
{
// some other code
char *sResult;
if( ( sResult = ReadToSerialPort()) >= 0)
{
printf("Response is %s\n", sResult);
// code to store char in string and put into db .
}
}
Thanks and regards,
SamPrat
You do not deallocate the buffer. You need to make free after you finished working with it.
char * getData()
{
char *buf = (char *)malloc(255);
// Fill buffer
return buf;
}
void anotherFunc()
{
char *data = getData();
// Process data
free(data);
}
In your case I think you should free the buffer after printf:
if( ( sResult = ReadToSerialPort()) >= 0)
{
printf("Response is %s\n", sResult);
// code to store char in string and put into db .
free(sResult);
}
UPDATE Static buffer
Another option to use static buffers. It could increase performance a little bit, but getData method will be not a thread-safe.
char buff[1024];
char *getData()
{
// Write data to buff
return buff;
}
int main()
{
char *data = getData();
printf("%s", data);
}
UPDATE Some notes about your code
int iMax = buffer+buffer_size-bufptr; - iMax will always be 1024;
I do not see any idea of using bufptr since its value is the same as buffer and you do not change it anywhere in your function;
iIn = read( fd, bufptr, buffer_size-1 );
You can replace bufptr[(int)iIn<iMax?iIn:iMax] = '\0'; with bufptr[iIn] = '\0';
if(bufptr != buffer) is always false and this is why your pointer is incorrect and you always return 0;
Do not forget to free the buffer if errno == EAGAIN is true. Currently you just return 0 without free(buffer).
Good luck ;)
Elalfer is partially correct. You do free() your buffer, but not in every case.
For example, when you reach if ( errno == EAGAIN ) and it evaluates to true, you return without doing free on your buffer.
The best would be to pass the buffer as a parameter and make it obvious that the user must free the buffer, outside the function. (this is what basically Elalfer sais in his edited answer).
Just realized this is a C question, I blame SO filtering for this :D sorry! Disregard the following, I'm leaving it so that comments still make sense.
The correct solution should use std::vector<char>, that way the destructor handles memory deallocation for you at the end of scope.
what is the purpose of the second pointer?
char *buffer = (char *)malloc(buffer_size);
char *bufptr = buffer;
what is the purpose of this?
int iMax = buffer+buffer_size-bufptr; // eh?
What is the purpose of this?
bufptr[(int)iIn<iMax?iIn:iMax] = '\0'; // so you pass in 1023 (iMax - 1), it reads 1023, you've effectively corrupted the last byte.
I would start over, consider using std::vector<char>, something like:
std::vector<char> buffer(1500); // default constructs 1500 chars
int iRead = read(fd, &buffer[0], 1500);
// resize the buffer if valid
if (iRead > 0)
buffer.resize(iRead); // this logically trims the buffer so that the iterators begin/end are correct.
return buffer;
Then in your calling function, use the vector<char> and if you need a string, construct one from this: std::string foo(vect.begin(), vect.end()); etc.
When you are setting the null terminator "bufptr[(int)iIn
bufptr[iMax]=>bufptr[1024]=>one byte beyond your allocation since arrays start at 0.
Also int this case "int iMax = buffer+buffer_size-bufptr;" can be re-written as iMax = buffer_size. It makes the code less readable.