|
I will check it.
Thank you
|
|
|
|
|
|
Thank you so much!
I will check it
|
|
|
|
|
You can use a product such as Code Jock which is a layer above MFC or .NET
- Michael Haephrati מיכאל האפרתי
|
|
|
|
|
Is there a way to tell the C++ runtime which heap to use to allocate objects with "new"? Can it be changed on the fly, or must the program be restarted?
I'd like to create custom heaps to hold objects, and then destroy the heaps when no longer needed, then create new heaps to take their places.
I have some legacy classes that leak memory, and I'm hoping to be able to mitigate the leaks by creating the objects in separate heaps, and then destroying the heaps after X many hours of run time.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
|
The "canonical" way to do this is with class-specific new / delete:
class Foo
{
public:
void* operator new(size_t blockSize)
{
}
void operator delete(void* p)
{
}
};
As long as you use the same heap for both allocation and deletion, things should work fine. As Richard MacCutchan says, a quick-and-dirty way to do this in Windows is by using the Windows heap APIs.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Thank you Daniel. Does this solution mean that I must call the constructor myself?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
No. When constructing an object using new (e.g. Foo* p = new Foo()), the compiler chooses the new operator to be called as follows:
- A class-specific operator new() (if present)
- The global operator new
It is the same for the delete operator. You may also replace the global new and delete operators with your own code:
void* operator new(size_t blockSize)
{
}
void operator delete(void* p)
{
}
Note that operators new and delete deal only with memory allocation/release. The compiler still calls the class' constructor to turn the raw memory into a class instance, and the destructor in order to turn a class instance back into raw memory.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Thank you.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Before I retired, I had to write, or service, programs that simulated behavior of polymer molecules. Each link in the polymer molecule chain could assume up to 3 possible rotation values. Later I wrote this program to do that sort of job:-
#define N 4
int main()
{int i, j, ncases, x[N], start[N], stop[N], n = N; ncases = 0;
for (i = 0; i<n; i++) { start[i] = x[i] = 0; stop[i] = 3; }
for (x[(i = n) - 1]--; i > 0; x[i] = start[i]) for (i--; (++x[i]) <= stop[i]; i = n - 1) {
ncases++;
for (j = 0; j < n; j++) putchar('0' + x[j]);
putchar(' '); }
printf("\n%d cases found\n~~~~~~~~~~~~~~\n", ncases);
printf("press a key to continue:"); i = getchar();
return 0;
}
This seems to do the same as:-
for( i[N-1] = start[N-1]; i[N-1] <= stop[N-1]; i[N-1]++ )
for( i[N-2] = start[N-2]; i[N-2] <= stop[N-2]; i[N-2]++ )
for( i[N-3] = start[N-3]; i[N-3] <= stop[N-3]; i[N-3]++ )
for( i[N-4] = ...............................
etc to ..
for( i[1] = start[1]; i[1] <= stop[1]; i[1]++ )
for( i[0] = start[0]; i[0] <= stop[0]; i[0]++ )
{ work to be done for every allowed combination of values of i[0:N-1] }
In case this piece of program text is any use to you.
modified 16-Aug-18 8:15am.
|
|
|
|
|
|
I am trying to revive a program that I wrote in years 2001 to 2005 for my old Borland C++ 4.51 compiler. The library functions that its compiled programs called, always ran in the mode of a character = 8 bits, not 16 bits. As this program largely handles text, not numerical values, it will have to compile to run with char = 8 bytes everywhere. For example, in this section:
int rundialogbox(HWND wn, HINSTANCE I, char*name,
BOOL CALLBACK /*_export*/ proc(HWND db, UINT M, WPARAM S, LPARAM L)) {
DLGPROC dp = MakeProcInstance((DLGPROC)proc, I);
int i = DialogBox(I, name, wn, dp); FreeProcInstance(dp); return i;}
I had type mismatch error of the type char* :: WCHAR*, until in menu Project / Properties I set the character mode from Unicode to Not Set; then this section compiled OK.
Whereupon, the next section
void diprintf(HWND db,int c,char*fmt,...){
char C[256];
vsprintf(C,fmt,(&fmt)+1);
SetDlgItemText(db,c,C);
};
failed with this error:
1>faces.cpp(80): error C2664: 'int vsprintf(char *const ,const char *const ,va_list)': cannot convert argument 3 from 'char **' to 'va_list'
1> faces.cpp(80): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
I replaced `char C[256];` by `WCHAR C[256];`, and compilation error still happened.
Does my Visual C++ still have an 8-bit-char-mode set of library functions? If so, how to call them?
modified 15-Aug-18 7:28am.
|
|
|
|
|
Anthony Appleyard wrote: Does my Visual C++ still have an 8-bit-char-mode set of library functions? If so, how to call them?
The "Not Set" should allow the project to use the ANSI functions. You've already made the correct change.
Anthony Appleyard wrote:
void diprintf(HWND db,int c,char*fmt,...)
{
char C[256];
vsprintf(C,fmt,(&fmt)+1);
SetDlgItemText(db,c,C);
};
failed with this error:
1>faces.cpp(80): error C2664: 'int vsprintf(char *const ,const char const ,va_list)': cannot convert argument 3 from 'char *' to 'va_list'
1> faces.cpp(80): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
The debugger error tells you exactly what the problem is. The third argument needs to be a va_list. Those old unsafe typecasts are no longer legal.
You can probably fix it with something like:
void diprintf(HWND db,int c,char*fmt,...)
{
char C[256];
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsprintf(C,fmt,arg_ptr);
SetDlgItemText(db,c,C);
};
The function looks unsafe. The function will overflow if the variable-argument list results in a string longer than 256 char. You should consider using the safer vsprintf_s.
vsprintf_s(C,256,fmt,arg_ptr);
Best Wishes,
-David Delaune
|
|
|
|
|
Thanks. It compiled OK. What should this become?
int discanf(HWND db, int c, char*fmt, ...) {
char C[256];
GetDlgItemText(db, c, C, 256);
C[255] = 0;
return vsscanf(C, fmt, (&fmt) + 1);
}
|
|
|
|
|
Anthony Appleyard wrote: What should this become?
Come on man, this is something that you can easily figure out. You've been a member here for over 10 years.
You know the old Chinese proverb?
If you give a man a fish he is hungry again in an hour. If you teach him how to catch a fish you feed him for his lifetime.
You've already had your daily fish. I highly encourage you to figure it out yourself. If you get stuck feel free to come back for more fish.
Best Wishes,
-大衛王
|
|
|
|
|
For a start having an int variable called c , and a char array called C is bad enough in the same module. But in the same function it is beyond ridiculous. Use proper meaningful unique names for all your variables.
|
|
|
|
|
Sorry. I started computer programming in the late 1960's, when computer storage was much smaller (80,000 words memory was big), under early compilers such as Atlas Autocode and Basic, and I got accustomed to one-letter and two-letter variable names.
Thanks for your help.
modified 15-Aug-18 12:02pm.
|
|
|
|
|
Anthony Appleyard wrote: I got accustomed to one-letter and two-letter variable names.
I confirmed that it compiles in Visual Studio 2017. I am calling it "C Notation" naming convention.
#define C 256
int Ƈ(HWND č, int c, char* Ç, ...)
{
char ₵[C];
va_list Ĉ;
va_start(Ĉ, Ç);
GetDlgItemText(č, c, ₵, C);
₵[C] = 0;
return vsscanf(₵, Ç, Ĉ);
}
If you use this... your coworkers will pick you up and throw you out of the office.
Best Wishes,
-David Delaune
|
|
|
|
|
There is something truly sublime about that code.
|
|
|
|
|
I started in 1966 and the only time I used single letter names was when coding in Fortran IV.
|
|
|
|
|
Hi, I read a block of code, like:
class Graph
{
public:
int V; vector<int> *adj;
Graph(int V);
void addEdge(int x, int y);
bool isRoute(int x, int y);
};
Graph::Graph(int V)
{
this->V = V;
this->adj = new vector<int>[V];
}
void Graph::addEdge(int x, int y) {
adj[x].push_back(y);
}
int main() {
Graph g(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
}
I wonder the adj is a pointer that points to a Vector object, and a vector object I think it's like an one-dimensional array, but the addEdge() operation, adj[x].push_back(y),it make another array[x,y].
in Main(), the structure of the vector object, seems like:
[5,2,0]
[4,0,1]
[2,3]
[3,1]
Then this is not an one-dimensional array.so this is a Vector object, or 4 vector objects?
Thanks
|
|
|
|
|
Not sure what any of that means. But why not use a POINT structure (or create your own), and then you can have a vector of points?
struct POINT
{
int x;
int y;
};
vector<POINT> pointList;
|
|
|
|
|
focusdoit wrote: I wonder the adj is a pointer that points to a Vector object
No, it's an array of vectors with V elements. So it's a two-dimensional data structure.
|
|
|
|
|
vector<int> *adj; //adjacency list
is it point to an Vector object?
|
|
|
|
|