HI All,
I was trying to overload new and delete to fix a memory leak problem in my project. But got stuck with some compilation error.
Currently this code is bit shabby
Here is my hdr file
#include <cstddef>
#include <iostream>
#include <list>
#include <stdarg.h>
#include <stdio.h>
using namespace std;
typedef unsigned int DWORD;
void AddTrack(DWORD addr, DWORD asize, const char *fname, DWORD lnum);
char *OutputDebugString (const char *fmt, ...);
void RemoveTrack(DWORD addr);
void DumpUnfreed();
#ifdef _DEBUG
#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW
void * operator new (unsigned int size, const char *file, int line)
{
void *ptr = (void *)malloc(size);
AddTrack((DWORD)ptr, size, file, line);
return(ptr);
}
/*inline void * operator new(unsigned int size)
{
void *ptr = (void *)malloc(size);
AddTrack((DWORD)ptr, size, _FILE_,_LINE_);
return(ptr);
}*/
void operator delete(void *p)
{
RemoveTrack((DWORD)p);
free(p);
}
#endif
char *OutputDebugString (const char *fmt, ...)
{
char *p = NULL;
size_t size = 1024;
int n = 0;
va_list ap;
if((p = (char*) malloc(size)) == NULL)
return NULL;
while(1) {
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
if(n > -1 && n < size)
return p;
/* failed: have to try again, alloc more mem. */
if(n > -1) /* glibc 2.1 */
size = n + 1;
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if((p = (char *)realloc (p, size)) == NULL)
return NULL;
}
}
typedef struct information {
DWORD address;
DWORD size;
char file[64];
DWORD line;
} ALLOC_INFO;
typedef list < ALLOC_INFO* > AllocList;
AllocList *allocList;
void AddTrack(DWORD addr, DWORD asize, const char *fname, DWORD lnum)
{
ALLOC_INFO *info;
if(!allocList) {
//allocList = new AllocList;
allocList = (AllocList*)malloc (sizeof (AllocList));
}
//info = new(ALLOC_INFO);
info = (ALLOC_INFO*) malloc (sizeof (ALLOC_INFO));
info->address = addr;
strncpy(info->file, fname, 63);
info->line = lnum;
info->size = asize;
allocList->insert(allocList->begin(), info);
}
void RemoveTrack(DWORD addr)
{
AllocList::iterator i;
if(!allocList)
if(!allocList)
return;
for(i = allocList->begin(); i != allocList->end(); i++)
{
if((*i)->address == addr)
{
allocList->remove((*i));
break;
}
}
}
void DumpUnfreed()
{
AllocList::iterator i;
DWORD totalSize = 0;
char buf[1024];
if(!allocList)
return;
for(i = allocList->begin(); i != allocList->end(); i++) {
sprintf(buf, "%-50s:\t\tLINE %d,\t\tADDRESS %d\t%d unfreed\n",
(*i)->file, (*i)->line, (*i)->address, (*i)->size);
OutputDebugString("%s",buf);
totalSize += (*i)->size;
}
sprintf(buf, "-----------------------------------------------------------\n");
OutputDebugString("%s",buf);
sprintf(buf, "Total Unfreed: %d bytes\n", totalSize);
OutputDebugString("%s",buf);
}
And my main.cpp is
#include "mynew.h"
int main()
{
char *ptr = new char;
DumpUnfreed();
return 0;
}
When i try to compile i get the following error
[root#dhcppc0 new]# !g
g++ main.cpp -D_DEBUG
mynew.h:25: error: declaration of ‘operator new’ as non-function
main.cpp: In function ‘int main()’:
main.cpp:9: error: no matching function for call to ‘operator new(unsigned int, const char [9], int)’
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/new:84: note: candidates are: void* operator new(size_t)
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/new:88: note: void* operator new(size_t, const std::nothrow_t&)
/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/new:94: note: void* operator new(size_t, void*)
I know there is some thing wrong with my #defines, but I am not sure what is wrong.
Can any one please bale me out of this
You've defined your new macro before your functions. Your code ends up looking like:
void *
operator new(__FILE__, __LINE__)(unsigned int size, const char *file, int line)
Which is obviously wrong. Your should move the macro definitions underneath the functions (or better is to keep those functions in a .cpp file you link with.) For what it's worth, new is a keyword and cannot be an identifier, so your program is, strictly speaking, ill-formed.
I recently posted my global memory operators framework. It might help you a bit.
the signature don't match it sould be void* operator new (size_t size).
overriding single object new signature is
static void * operator new(site_t size),
roni
Related
I can not get my c++ application to work properly, i will paste my simple memory class and a test app here.
Right now i get an access violation and no output when i run it in the console. I use Visual Studio 2015.
I seem to haave problems with my car class, not sure what could be wrong. And i ge some error message if i try to debug. I have no idea how to fix it...
#define WIN32_LEAN_AND_MEAN
enum memtype {typechar = 1, typeint};
class Mem
{
public:
Mem(int size);
void * alloc(memtype t);
void * ptr();
void release();
~Mem();
private:
int sizebytes;
void * p;
};
#include <new.h>
#include "Mem.h"
Mem::Mem(int size)
{
sizebytes = size;
}
void * Mem::alloc(memtype t)
{
if (t==typechar)
{
p = (char *)new char(sizebytes);
return p;
}
}
void * Mem::ptr()
{
return p;
}
void Mem::release()
{
if(p)
delete p;
}
Mem::~Mem()
{
if(p)
delete p;
}
#include "Mem.h"
#include <stdio.h>
int check(void * p)
{
int retval = 0;
if (p == NULL)
{
printf("Memory Fail: NULL pointer...\n");
retval = 0;
}
else
retval = 1;
return retval;
}
class Car
{
public:
Car::Car()
{
Car::name = 0;
Car::brand = 0;
Car::type = 0;
}
int Car::alloc(char *inname, char *inbrand, char *intype)
{
Car::name = new Mem(sizeof(*inname));
if (!check(Car::name->alloc(typechar)))
return 0;
printf("%s", sizeof(*inname));
Car::brand = new Mem(sizeof(*inbrand));
if (!check(Car::brand->alloc(typechar)))
return 0;
printf("%s", sizeof(*inbrand));
Car::type = new Mem(sizeof(*intype));
if (!check(Car::type->alloc(typechar)))
return 0;
printf("%s", sizeof(*intype));
/*sprintf?*/
sprintf_s((char *)Car::name->ptr(), sizeof(*inname), "%s", inname);
sprintf_s((char *)Car::brand->ptr(), sizeof(*inbrand), "%s", inbrand);
sprintf_s((char *)Car::type->ptr(), sizeof(*intype), "%s", intype);
return 1;
}
char * Car::getName()
{
if(Car::name!=0)
return (char *)Car::name->ptr();
}
char * Car::getBrand()
{
if(Car::brand!=0)
return (char *)Car::brand->ptr();
}
char * Car::getType()
{
if(Car::type!=0)
return (char *)Car::type->ptr();
}
Car::~Car()
{
if (Car::name != 0)
delete Car::name;
if (Car::brand != 0)
delete Car::brand;
if (Car::type != 0)
delete Car::type;
}
private:
Mem *name, *brand, *type;
};
void store()
{
}
int main()
{
Mem cartype1(sizeof("Sedan"));
cartype1.alloc(typechar);
check(cartype1.ptr());
Mem cartype2(sizeof("Van"));
cartype2.alloc(typechar);
check(cartype2.ptr());
Mem cartype3(sizeof("Pickup"));
cartype3.alloc(typechar);
check(cartype3.ptr());
sprintf((char *)cartype1.ptr(), "%s", "Sedan");
sprintf((char *)cartype2.ptr(), "%s", "Van");
sprintf((char *)cartype3.ptr(), "%s", "Pickup");
Mem carname(sizeof("Supah Car"));
carname.alloc(typechar);
check(carname.ptr());
Mem carbrand(sizeof("Supah"));
carbrand.alloc(typechar);
check(carbrand.ptr());
sprintf((char *)carname.ptr(), "%s", "Supah Car");
sprintf((char *)carbrand.ptr(), "%s", "Supah");
Car test;
test.alloc((char *)carname.ptr(), (char *)carbrand.ptr(), (char *)cartype1.ptr());
printf("%s is of brand %s and type %s\n", test.getName(), test.getBrand(), test.getType());
char * nullptrtest = NULL;
printf_s("%d", &test);
printf_s("sizeof int %d\n", sizeof(int));
printf_s("Test %s\n", carname.ptr());
return 1;
}
int Car::alloc(char *inname, char *inbrand, char *intype)
{
Car::name = new Mem(sizeof(*inname));
sizeof *inname will give you sizeof(char) == 1
So your name member has allocated array of 1 char exactly.
You later write to this array a lot more. As a result your heap is corrupted.
I do not know why you want to play with emulating memory allocation instead of using std::string - but you need to allocate at least strlen(inname)+1 bytes to store inname
Why does strcat gives me its version of str1? As far as I know there has to be & thing before paramatater in function prototype and implementation if you want to get it editted, but I don't see it here.
char *strcat( char *str1, const char *str2 );
How do I edit this function so that it would only return new string but leave out the ones I give it?
My try
char *strApp(char *dest, const char *src)
{
size_t i,j;
size_t k = 0;
for (i = 0; dest[i] != '\0'; i++);
char rdest[100];
do {
rdest[k] = dest[k];
} while(++k<=i);
for (j = 0; src[j] != '\0'; j++)
rdest[i+j] = src[j];
rdest[i+j] = '\0';
return rdest;
}
It damages second string. Could anyone give me safe and correct version? Thanks in advance.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strApp(const char *s1, const char *s2)
{
char *pointer = malloc(strlen(s1) + strlen(s2) + 1);
if (pointer == NULL)
{
perror("failed to allocate memory");
exit(EXIT_FAILURE);
}
return strcat(strcpy(pointer, s1), s2);
}
int main()
{
char *s1 = "original";
char *s2 = " modified";
char *s3 = strApp(s1, s2);
printf("%s\n", s1);
printf("%s\n", s2);
printf("%s\n", s3);
free(s3);
return 0;
}
Just trying to point out you don't need to completely rewrite strcat() to get what you want.
strcat is, by definition, altering the target. If you don't want to, you should make a copy yourself in a target memory location you allocate yourself.
You've tagged your question with both C and C++. I'm providing a C solution. Adjustments may be needed for C++.
#include <stdlib.h>
#include <string.h>
char* strdupcat(const char* s1, const char* s2) {
size_t s1_len = strlen(s1);
size_t s2_len = strlen(s2);
char* s = malloc(s1_len + s2_len + 1);
if (s == NULL)
return NULL;
{
char* s_end = s;
s_end = mempcpy(s_end, s1, s1_len);
s_end = mempcpy(s_end, s2, s2_len);
*s_end = '\0';
}
return s;
}
Example usage:
#include <stdio.h>
int main() {
char* s = strdupcat("abc", "def");
if (s == NULL) {
perror("Can't concatenate");
return EXIT_FAILURE;
}
puts(s);
free(s);
return EXIT_SUCCESS;
}
This function is used similarly to strdup.
DESCRIPTION
The strdupcat() function returns a pointer to a new string which is a duplicate of the string s1 with a duplicate of string s2 appended. Memory for the new string is obtained with malloc(3), and can be freed with free(3).
RETURN VALUE
The strdupcat() function returns a pointer to the duplicated string, or NULL if insufficient memory was available.
ERRORS
ENOMEM Insufficient memory available to allocate the new string.
You can use strerror or perror to obtain an error message when strdupcat() returns NULL.
Here's a version that accepts an arbitrary number of arguments:
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
char* strdupcatmany(int dummy, ...) {
#define strdupcatmany(...) strdupcatmany(0, __VA_ARGS__, NULL)
size_t len = 0;
char* s;
char* s_dst;
const char* s_src;
va_list ap;
va_start(ap, dummy);
while (1) {
s_src = va_arg(ap, const char*);
if (s_src == NULL)
break;
len += strlen(s_src);
}
va_end(ap);
s = malloc(len + 1);
if (s == NULL)
return NULL;
s_dst = s;
va_start(ap, dummy);
while (1) {
s_src = va_arg(ap, const char*);
if (s_src == NULL)
break;
s_dst = stpcpy(s_dst, s_src);
}
va_end(ap);
*s_dst = '\0';
return s;
}
For example,
#include <stdio.h>
int main() {
char* s = strdupcatmany("abc", "def", "ghi");
if (s == NULL) {
perror("Can't concatenate");
return EXIT_FAILURE;
}
puts(s);
free(s);
return EXIT_SUCCESS;
}
Note: I don't know how portable __VA_ARGS__ args is.
My purpose is quite simple: when I start the mongoose server, the server will initialize a variable which is defined by me. To do this, I hooked __libc_start_main. Then when the server receives a request, it will print out that initialized variable. To do this, I hooked recv. Below is my code.
#include <string>
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include "common-structure.h"
# define dprintf(fmt...)
data datainfo; //defined in common-structure.h
typedef int (*main_type)(int, char**, char**);
struct arg_type
{
char **argv;
int (*main_func) (int, char **, char **);
};
main_type saved_init_func = NULL;
void tern_init_func(int argc, char **argv, char **env){
dprintf("%04d: __tern_init_func() called.\n", (int) pthread_self());
if(saved_init_func)
saved_init_func(argc, argv, env);
datainfo.age = 10;
}
typedef void (*fini_type)(void*);
fini_type saved_fini_func = NULL;
extern "C" int my_main(int argc, char **pt, char **aa)
{
int ret;
arg_type *args = (arg_type*)pt;
dprintf("%04d: __libc_start_main() called.\n", (int) pthread_self());
ret = args->main_func(argc, args->argv, aa);
return ret;
}
extern "C" int __libc_start_main(
void *func_ptr,
int argc,
char* argv[],
void (*init_func)(void),
void (*fini_func)(void),
void (*rtld_fini_func)(void),
void *stack_end)
{
typedef void (*fnptr_type)(void);
typedef int (*orig_func_type)(void *, int, char *[], fnptr_type,
fnptr_type, fnptr_type, void*);
orig_func_type orig_func;
arg_type args;
void * handle;
int ret;
// Get lib path.
Dl_info dli;
dladdr((void *)dlsym, &dli);
std::string libPath = dli.dli_fname;
libPath = dli.dli_fname;
size_t lastSlash = libPath.find_last_of("/");
libPath = libPath.substr(0, lastSlash);
libPath += "/libc.so.6";
libPath = "/lib/x86_64-linux-gnu/libc.so.6";
if(!(handle=dlopen(libPath.c_str(), RTLD_LAZY))) {
puts("dlopen error");
abort();
}
orig_func = (orig_func_type) dlsym(handle, "__libc_start_main");
if(dlerror()) {
puts("dlerror");
abort();
}
dlclose(handle);
dprintf("%04d: __libc_start_main is hooked.\n", (int) pthread_self());
args.argv = argv;
args.main_func = (main_type)func_ptr;
saved_init_func = (main_type)init_func;
saved_fini_func = (fini_type)rtld_fini_func;
ret = orig_func((void*)my_main, argc, (char**)(&args),
(fnptr_type)tern_init_func, (fnptr_type)fini_func,
rtld_fini_func, stack_end);
return ret;
}
//hook recv
extern "C" ssize_t recv(int sockfd, void *buf, size_t len, int flags)
{
ssize_t (*orig_recv)(int sockfd, void *buf, size_t len, int flags);
orig_recv = dlsym(RTLD_NEXT, "recv");
orig_recv(sockfd, buf, len, flags);
printf("age is %d\n", datainfo.age);
}
However, when I makefile, I get the error: invalid conversion from ‘void*’ to ‘ssize_t (*)(int, void*, size_t, int) coming from dlsym(RTLD_NEXT, "recv");. My another question is can I achieve my goal in this way? If not, what is the correct way?
C++ is much more strongly typed than C, you need to explicitly cast void * to the correct type.
For example:
extern "C" ssize_t recv(int sockfd, void *buf, size_t len, int flags)
{
using orig_recv_t = ssize_t (*)(int, void *, size_t, int);
// Or for pre C++11 compilers: typedef ssize_t (*orig_recv_t)(int, void *, size_t, int);
orig_recv_t orig_recv;
orig_recv = reinterpret_cast<orig_recv_t>(dlsym(RTLD_NEXT, "recv"));
orig_recv(sockfd, buf, len, flags);
printf("age is %d\n", datainfo.age);
}
if I have this function:
printAll(const char *message, ...)
{
va_list argptr = NULL;
va_start(argptr, message);
// todo: how to printf all the arguments in the message?
va_end(argptr);
}
Suppose I call the function like this:
printAll("My info: Value1 = %d, Value 2=%d", 1, 2);
In this line: // todo: how to printf all the arguments in the message?
How can I print them all in order to have:
My info: Value1 = 1, Value 2=2
You're looking for the vprintf() function which was designed to do exactly this:
vprintf(message, argptr);
The v*printf() family of functions work basically in the same way as their normal counterparts, except they take a va_list instead of varargs. They don't call va_end() for you, so the way you have it now is correct.
Here's a sketch of the general idea (though a finished version, has to deal with quite a few more things such as field width, precision, more conversions, etc.
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
int my_vfprintf(FILE *file, char const *fmt, va_list arg) {
int int_temp;
char char_temp;
char *string_temp;
char ch;
int length = 0;
char buffer[512];
while ( ch = *fmt++) {
if ( '%' == ch ) {
switch (ch = *fmt++) {
/* %% - print out a single % */
case '%':
fputc('%', file);
length++;
break;
/* %c: print out a character */
case 'c':
char_temp = va_arg(arg, int);
fputc(char_temp, file);
length++;
break;
/* %s: print out a string */
case 's':
string_temp = va_arg(arg, char *);
fputs(string_temp, file);
length += strlen(string_temp);
break;
/* %d: print out an int */
case 'd':
int_temp = va_arg(arg, int);
itoa(int_temp, buffer, 10);
fputs(buffer, file);
length += strlen(buffer);
break;
/* %x: print out an int in hex */
case 'x':
int_temp = va_arg(arg, int);
itoa(int_temp, buffer, 16);
fputs(buffer, file);
length += strlen(buffer);
break;
}
}
else {
putc(ch, file);
length++;
}
}
return length;
}
int my_printf(char const *fmt, ...) {
va_list arg;
int length;
va_start(arg, fmt);
length = my_vfprintf(stdout, fmt, arg);
va_end(arg);
return length;
}
int my_fprintf(FILE *file, char const *fmt, ...) {
va_list arg;
int length;
va_start(arg, fmt);
length = my_vfprintf(file, fmt, arg);
va_end(arg);
return length;
}
#ifdef TEST
int main() {
my_printf("%s", "Some string");
return 0;
}
#endif
Here is a printAll() that will do exactly as you would like...
#ifdef __cplusplus
#include <cstring>
#include <cstdio>
#include <cstdarg>
using namespace std;
#else
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#endif
void printAll(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
const size_t MAX_LEN = 1023;
#ifdef __cplusplus
char msg[MAX_LEN+1] = {0};
#else
char msg[MAX_LEN+1];
for (int i = 0; i < MAX_LEN+1; i++)
{
msg[i] = 0;
}
#endif
vsnprintf(msg, MAX_LEN, fmt, ap);
printf("%s\n", msg);
va_end(ap);
}
int main() {
printAll("My info: Value1 = %d, Value 2=%d", 1, 2);
return 0;
}
My info: Value1 = 1, Value 2=2
I've been at this for some time now. I need a basic IRC Ping Pong function to return the the proper response when the IRC server pings. I changed the name of the function get() to something else and I'm still getting the error. I thought perhaps the function name get() was already defined in one of the includes or something else.
#include "stdafx.h"
#include "Ping_Pong.h"
#include <iostream>
#include <ws2tcpip.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CWinApp theApp;
#define MT4_EXPFUNC __declspec(dllexport)
#pragma comment(lib, "Ws2_32.lib")
class MT4_EXPFUNC IRC {
private:
char buf[513];
char rbuf[513];
char sbuf[513];
char *tok;
int recv_bytes;
int irc_socket;
struct addrinfo hints;
struct addrinfo *results;
public:
char *nick, *user, *host, *chan, *type, *mesg;
int irc_connect(const char *host, const char *port, const char *nick);
void socket_err(const char* err_string);
//int join(const char *channel);
This is the name of the function in question
int __stdcall get();
char *check(const char* test_str);
char *pop_arg(char **save_ptr);
int init_comarg();
int say(const char *channel, const char *message);
int sayf(const char *channel, const char *message, ...);
int mode(const char *channel, const char *mode, char *target);
//void die();
};
And this is the function I'm having a problem with.
MT4_EXPFUNC int __stdcall IRC::get()
{
memset(rbuf, 0, 513);
recv_bytes = recv(irc_socket, rbuf, sizeof(rbuf), 0);
if (recv_bytes <= 0) {
return -1;
}
std::cout << rbuf;
// Auto-Respond to PING messages.
if (rbuf[0] == 'P' && rbuf[1] == 'I') {
tok = strtok(rbuf, "PING :");
sprintf(buf, "PONG %s", tok-1 );
send(irc_socket, buf, strlen(buf), 0);
std::cout << buf;
memset(buf, 0, 513);
}
if ( strstr(rbuf, "PRIVMSG")) {
memcpy(sbuf, rbuf, 513);
nick = strtok(sbuf, "!") + 1;
user = strtok(NULL, "#");
host = strtok(NULL, " ");
type = strtok(NULL, " ") - 1;
chan = strtok(NULL, " ");
mesg = strtok(NULL, ":");
}
return 1;
}
In the tutorial linked below, a .def file was suggested with the following code:
Library "Ping_Pong"
Export get
I removed the .def and it worked.
http://www.xpworx.com/metatrader-mql-articles/mql4-articles/create-your-own-metatrader-extension-dll.php