Jump to content
  • Advertisement
Sign in to follow this  
JasonL220

thinking in c++ vol 2 question

This topic is 4577 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

in the section on memory leak detection it says that the code does not following the standard why is that?

Share this post


Link to post
Share on other sites
Advertisement
1. Even though it’s technically illegal, it works on many compilers.

//: C02:MemCheck.h
#ifndef MEMCHECK_H
#define MEMCHECK_H
#include <cstddef> // For size_t

// Usurp the new operator (both scalar and array versions)
void* operator new(std::size_t, const char*, long);
void* operator new[](std::size_t, const char*, long);
#define new new (__FILE__, __LINE__)

extern bool traceFlag;
#define TRACE_ON() traceFlag = true
#define TRACE_OFF() traceFlag = false

extern bool activeFlag;
#define MEM_ON() activeFlag = true
#define MEM_OFF() activeFlag = false

#endif // MEMCHECK_H ///:~


//: C02:MemCheck.cpp {O}
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstddef>
using namespace std;
#undef new

// Global flags set by macros in MemCheck.h
bool traceFlag = true;
bool activeFlag = false;

namespace {

// Memory map entry type
struct Info {
void* ptr;
const char* file;
long line;
};

// Memory map data
const size_t MAXPTRS = 10000u;
Info memMap[MAXPTRS];
size_t nptrs = 0;

// Searches the map for an address
int findPtr(void* p) {
for(size_t i = 0; i < nptrs; ++i)
if(memMap.ptr == p)
return i;
return -1;
}

void delPtr(void* p) {
int pos = findPtr(p);
assert(pos >= 0);
// Remove pointer from map
for(size_t i = pos; i < nptrs-1; ++i)
memMap = memMap[i+1];
--nptrs;
}

// Dummy type for static destructor
struct Sentinel {
~Sentinel() {
if(nptrs > 0) {
printf("Leaked memory at:\n");
for(size_t i = 0; i < nptrs; ++i)
printf("\t%p (file: %s, line %ld)\n",
memMap.ptr, memMap.file, memMap.line);
}
else
printf("No user memory leaks!\n");
}
};

// Static dummy object
Sentinel s;

} // End anonymous namespace

// Overload scalar new
void*
operator new(size_t siz, const char* file, long line) {
void* p = malloc(siz);
if(activeFlag) {
if(nptrs == MAXPTRS) {
printf("memory map too small (increase MAXPTRS)\n");
exit(1);
}
memMap[nptrs].ptr = p;
memMap[nptrs].file = file;
memMap[nptrs].line = line;
++nptrs;
}
if(traceFlag) {
printf("Allocated %u bytes at address %p ", siz, p);
printf("(file: %s, line: %ld)\n", file, line);
}
return p;
}

// Overload array new
void*
operator new[](size_t siz, const char* file, long line) {
return operator new(siz, file, line);
}

// Override scalar delete
void operator delete(void* p) {
if(findPtr(p) >= 0) {
free(p);
assert(nptrs > 0);
delPtr(p);
if(traceFlag)
printf("Deleted memory at address %p\n", p);
}
else if(!p && activeFlag)
printf("Attempt to delete unknown pointer: %p\n", p);
}

// Override array delete
void operator delete[](void* p) {
operator delete(p);
} ///:~


on about page 95

Share this post


Link to post
Share on other sites
I believe the line:
#define new new (__FILE__, __LINE__)
is illegal. I'm pretty sure that #defining a keyword isn't allowed.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The most obvious thing is the implementation of operator new, most notably:


// Overload scalar new
void*
operator new(size_t siz, const char* file, long line) {
void* p = malloc(siz);
if(activeFlag) {
if(nptrs == MAXPTRS) {
printf("memory map too small (increase MAXPTRS)\n");
exit(1);
}
memMap[nptrs].ptr = p;
memMap[nptrs].file = file;
memMap[nptrs].line = line;
++nptrs;
}
if(traceFlag) {
printf("Allocated %u bytes at address %p ", siz, p);
printf("(file: %s, line: %ld)\n", file, line);
}
return p;
}



1) It doesn't handle the size == 0 case
2) It doesn't call the new-handler if insufficient memory is available
3) It doesn't contain a loop around the allocation
4) It doesn't throw std::bad_alloc if it can't satisfy the request

Share this post


Link to post
Share on other sites
@jasonL220: Yes, one can overload the operator.

@Yohumbus: You're right. Anything that would syntaxically be eligible to be an identifier can be #defined (regardless of the fact they are keywords or not, since preprocessing occurs, as the name says, before compiling.

Valid:
#define new delete // very powerful ;)
#define true false
etc.

Invalid:
#define 0 1

http://www-ccs.ucsd.edu/c/preproc.html#Preprocessing%20Tokens

Share this post


Link to post
Share on other sites
Guest Anonymous Poster

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!