• What Do You Need Help With? V8
    1,074 replies, posted
In Chrome, the dev tools shows the CSS for the selected element but is there anyway to see what styles are superseding another?
[QUOTE=Adelle Zhu;52133330]In Chrome, the dev tools shows the CSS for the selected element but is there anyway to see what styles are superseding another?[/QUOTE] The styles should be shown in order already, with the most important one on top. Rules that were superseded should be struck like this: [img]https://cdn.discordapp.com/attachments/179908939083677696/305086371465396225/unknown.png[/img] [editline]whoops[/editline] Whoops, that's Firefox. I'll check Chrome. [editline]phew[/editline] Same thing (which explains why I mixed it up): [img]https://cdn.discordapp.com/attachments/179908939083677696/305087337262612491/unknown.png[/img]
So I've gotten the autocomplete to work a bit. However now I'm running into weird behavior. All of the results in the suggested list read "undefined" and the function returns: [code] Uncaught TypeError: Cannot read property 'toLowerCase' of undefined at HTMLInputElement.<anonymous> (jquery.easy-autocomplete.min.js:10) at HTMLInputElement.dispatch (jquery-3.1.1.min.js:3) at HTMLInputElement.q.handle (jquery-3.1.1.min.js:3) at Object.trigger (jquery-3.1.1.min.js:4) at Object.simulate (jquery-3.1.1.min.js:4) at HTMLDocument.c (jquery-3.1.1.min.js:4) [/code] Now I can continue typing and making the results list shrink as I get more specific, but the all list elements still read "undefined." The json is returning properly and Chrome's response renders from the callback like this: [code] [["Canine Gilbert"], ["Canine Bennie"], ["Canine Jake"], ["Canine Mochi"], ["Canine Buddy"], ["Canine Max"]] [/code] I have a hunch that the autocomplete script is not reading that list properly and it may be because of my choice to use json.dumps(results) to create that list in the callback function. What should I investigate here?
[QUOTE=brianosaur;52133111]did you add an __init__.py file in the directory?[/QUOTE] I did, but whether I have it or not didn't seem to make a difference. Is a relative local import even possible in Python 3?
[QUOTE=Adelle Zhu;52134405][...] What should I investigate here?[/QUOTE] I have a hunch, but I'd have to see your list access code. Did you forget to access the elements of the inner arrays?
A while ago I decided to try my hand at implementing 2D lighting with OpenGL and SFML. I ended up with this: (I dont know how to embed sorry) [url]http://i.imgur.com/zo1YRny.gifv[/url] It looks fine (to me anyway) and can support upwards of 500 lights (tested in debug mode, imagine release) but I'm not overly fond of the implementation. Currently I have 3 render targets. 1 has the lights rendered additively to it, the second has all the diffuse textures rendered to it and the third has all the normal textures rendered to it. The diffuse and normal RTs are uniforms for the shader which works on the light RT. I'd like to not have such a pain in the ass setup but I have no idea how to make the design better. The full source code can be found here: [url]https://bitbucket.org/GamerGambit/sfml-gsl-lighting[/url] Any and all help is appreciated. [editline]22nd April 2017[/editline] I have been refered to this: [url]http://ncase.me/sight-and-light/[/url] however, I'm not sure how to apply this to shaders since the Vertex shader is per-vertex and the fragment shader is per-fragment per-vertex so I'm not sure how to do ray tracing for each vertex.
[QUOTE=tschumann;52134986]I did, but whether I have it or not didn't seem to make a difference. Is a relative local import even possible in Python 3?[/QUOTE] How exactly are you doing the import statement? It is possible, but I don't know about it being a relative path. You should be able to use from...Import syntax.
[QUOTE=brianosaur;52136004]How exactly are you doing the import statement? It is possible, but I don't know about it being a relative path. You should be able to use from...Import syntax.[/QUOTE] What I have looks like this: scrape/__init__.py (empty) scrape/scrape.py scrape/test.py In test.py the relevant bits are [code] sys.path.append('..') from scrape.scrape import Page [/code] That works but I want to move away from the sys.path.append I've tried a bunch of different things for the import Page bit but everything that StackOverflow/various blogs has said doesn't work or is equally hacky (or involves splitting things up into separate Python packages which I don't want to do).
[QUOTE=Tamschi;52135549]I have a hunch, but I'd have to see your list access code. Did you forget to access the elements of the inner arrays?[/QUOTE] I've been trying to read through the script and it's reinforcing my hatred for anything java related. I'm catching the exception in chrome and when it shows the script it fucking renames all of the functions to letters for some reason. I managed to find the breakpoint in the original and it looks like the phrase it's trying to lowercase is not defined. I still think it's being broken by SQL returning a list of lists.
[QUOTE=Adelle Zhu;52141597]I've been trying to read through the script and it's reinforcing my hatred for anything java related. I'm catching the exception in chrome and when it shows the script it fucking renames all of the functions to letters for some reason. I managed to find the breakpoint in the original and it looks like the phrase it's trying to lowercase is not defined. I still think it's being broken by SQL returning a list of lists.[/QUOTE] You mean JavaScript and not Java, right? The function renaming is probably due to a build tool you use. (Minify? Uglify?) You can tell these to emit a 'source map', even if you chain them. Chrome will detect these and offer to show the original code if you drag your source folder into the dev tools ([editline]edit[/editline] or will just show it immediately, not sure). [URL="https://github.com/Microsoft/vscode-chrome-debug"]You can also debug your code directly from VS Code if you use that.[/URL] It works with any compiler that generates a source map and is significantly more convenient. The one downside is that opening the developer tools in Chrome closes the connection, which can kill the browser depending on your configuration. [URL="https://gist.github.com/Tamschi/e11576257e542d9dc5d9980e424eeb5d"]Here's mine.[/URL] [editline]24th April 2017[/editline] You also should change your SQL query/server endpoint to return something more sane if possible. I'm not proficient at it, but if you post the query here I can probably tell if there's anything wrong with it.
[QUOTE=Tamschi;52141667]You mean JavaScript and not Java, right? The function renaming is probably due to a build tool you use. (Minify? Uglify?) You can tell these to emit a 'source map', even if you chain them. Chrome will detect these and offer to show the original code if you drag your source folder into the dev tools. [URL="https://github.com/Microsoft/vscode-chrome-debug"]You can also debug your code directly from VS Code if you use that.[/URL] It works with any compiler that generates a source map and is significantly more convenient. The one downside is that opening the developer tools in Chrome closes the connection, which can kill the browser depending on your configuration. [URL="https://gist.github.com/Tamschi/e11576257e542d9dc5d9980e424eeb5d"]Here's mine.[/URL] [editline]24th April 2017[/editline] You also should change your SQL query/server endpoint to return something more sane if possible. I'm not proficient at it, but if you post the query here I can probably tell if there's anything wrong with it.[/QUOTE] I fixed it. This plugin expects a list of dictionaries. The undefined part was the script looking for a key and value but only finding a value. Which is why one of the functions showed up the debugger with whatever was typed in. Also, I'm using PyCharm since this is a Flask project, so I'm limited but there isn't much more JS to do.
[QUOTE=tschumann;52137414]What I have looks like this: scrape/__init__.py (empty) scrape/scrape.py scrape/test.py In test.py the relevant bits are [code] sys.path.append('..') from scrape.scrape import Page [/code] That works but I want to move away from the sys.path.append I've tried a bunch of different things for the import Page bit but everything that StackOverflow/various blogs has said doesn't work or is equally hacky (or involves splitting things up into separate Python packages which I don't want to do).[/QUOTE] I believe you can have another directory that holds your code. Make a src/ folder and put your scrape script in there, and then another test/ folder for test files. Put __init__.py files in each of those folders. I'm pretty sure that will solve your issue.
So could somebody explain to me as simple as possible how to convert a SDL_Surface to OpenGL texture? C++ of course. Maybe there are other ways to turn an image into a texture but they seem just as complicated. [editline]24th April 2017[/editline] Nevermind, looks like I was overthinking it, it was actually rather easy.
[QUOTE=brianosaur;52142936]I believe you can have another directory that holds your code. Make a src/ folder and put your scrape script in there, and then another test/ folder for test files. Put __init__.py files in each of those folders. I'm pretty sure that will solve your issue.[/QUOTE] Yeah I figured I could do that but was looking for a way to keep it all in the same directory.
In my UNIX class we are supposed to write a command interpreter using the UNIX Standard Library functions fork(), wait() and exec(). The program will prompt the user for a command with arguments to execute. Ex: ls -l. Where ls is the command and -l is the argument. This is the output required: [CODE]% ./z123456 Enter command: mkdir one Enter command: touch one/file one/other one/more Enter command: ls -l one total 0 -rw-r--r-- 1 student student 0 Apr 3 13:03 file -rw-r--r-- 1 student student 0 Apr 3 13:03 more -rw-r--r-- 1 student student 0 Apr 3 13:03 other Enter command: gobly gook gobly: No such file or directory Enter command: cd one cd: No such file or directory Enter command: exit %[/CODE] The issue is that the instructor says it can take up to 4 arguments. I am not sure how to do this. The exec function takes an array of c strings as an argument but not of strings. Basically, what I am asking is. How do I recreate the argc, argv[] that the main function holds as parameters. I tried to do a for loop and use cin to add each argument to an array of strings but I am not sure how to convert those strings into C strings and the exec function complains when I try to use it. Thanks in advance.
Ok now I'm really fucking confused. I have a winforms application, it has a control that can't be placed from the designer so I manually add it in the constructor - this is fine - on resize of the form it adjusts the sizes of the controls including the manually added one - this is fine too. Now on my computer (Windows 10), the ResumeLayout() function inside InitializeControls() doesn't resize the form and everything is fine, but for some reason unbeknownst to me running it on Windows 7 [I]does[/I] resize the form in that method causing a null reference exception. I dunno if a stacktrace would be any help but here's one any way: [code]Application: What JSON.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.NullReferenceException Stack: at What_JSON.MainForm.ScaleControls() at What_JSON.MainForm.MainForm_Resize(System.Object, System.EventArgs) at System.Windows.Forms.Form.OnResize(System.EventArgs) at System.Windows.Forms.Control.OnSizeChanged(System.EventArgs) at System.Windows.Forms.Control.UpdateBounds(Int32, Int32, Int32, Int32, Int32, Int32) at System.Windows.Forms.Control.UpdateBounds(Int32, Int32, Int32, Int32) at System.Windows.Forms.Control.SetBoundsCore(Int32, Int32, Int32, Int32, System.Windows.Forms.BoundsSpecified) at System.Windows.Forms.Form.SetBoundsCore(Int32, Int32, Int32, Int32, System.Windows.Forms.BoundsSpecified) at System.Windows.Forms.Control.ScaleControl(System.Drawing.SizeF, System.Windows.Forms.BoundsSpecified) at System.Windows.Forms.ScrollableControl.ScaleControl(System.Drawing.SizeF, System.Windows.Forms.BoundsSpecified) at System.Windows.Forms.Form.ScaleControl(System.Drawing.SizeF, System.Windows.Forms.BoundsSpecified) at System.Windows.Forms.Control.ScaleControl(System.Drawing.SizeF, System.Drawing.SizeF, System.Windows.Forms.Control) at System.Windows.Forms.ContainerControl.Scale(System.Drawing.SizeF, System.Drawing.SizeF, System.Windows.Forms.Control) at System.Windows.Forms.ContainerControl.PerformAutoScale(Boolean, Boolean) at System.Windows.Forms.ContainerControl.OnLayoutResuming(Boolean) at System.Windows.Forms.Control.ResumeLayout(Boolean) at What_JSON.MainForm.InitializeComponent() at What_JSON.MainForm..ctor() at What_JSON.Program.Main()[/code] [URL="https://helifreak.club/files/what.src.7z"]Source[/URL]. The easy solution is to just check in ScaleControls for null and this works but I just want to know why the fuck it's running functionally code different on each OS. [editline]25th April 2017[/editline] [QUOTE=BooTs;52146981]In my UNIX class we are supposed to write a command interpreter using the UNIX Standard Library functions fork(), wait() and exec(). The program will prompt the user for a command with arguments to execute. Ex: ls -l. Where ls is the command and -l is the argument. This is the output required: [CODE]% ./z123456 Enter command: mkdir one Enter command: touch one/file one/other one/more Enter command: ls -l one total 0 -rw-r--r-- 1 student student 0 Apr 3 13:03 file -rw-r--r-- 1 student student 0 Apr 3 13:03 more -rw-r--r-- 1 student student 0 Apr 3 13:03 other Enter command: gobly gook gobly: No such file or directory Enter command: cd one cd: No such file or directory Enter command: exit %[/CODE] The issue is that the instructor says it can take up to 4 arguments. I am not sure how to do this. The exec function takes an array of c strings as an argument but not of strings. Basically, what I am asking is. How do I recreate the argc, argv[] that the main function holds as parameters. I tried to do a for loop and use cin to add each argument to an array of strings but I am not sure how to convert those strings into C strings and the exec function complains when I try to use it. Thanks in advance.[/QUOTE] [url]http://www.cplusplus.com/reference/string/string/c_str/[/url] should do what you want.
-snip-
I have this C++ code to obtain all the available video resolutions for my game: [code] cout << "Obtaining available display modes..." << endl; int *index = new int; SDL_DisplayMode *dm = new SDL_DisplayMode; for ((*index) = 0; (*index) < SDL_GetNumDisplayModes(0); (*index)++) { result = SDL_GetDisplayMode(0, *index, dm); if (result < 0) { logError(SDL_GetError()); return 3; } availDM[*index] = *dm; cout << "Registered display mode " << dm->w << "x" << dm->h << "@" << dm->refresh_rate << "Hz" << endl; } delete dm; delete index;[/code] Compiles successfully, but running it gives me this: [t]http://i.imgur.com/xdGakXi.png[/t] As soon as I remove the line [code]availDM[*index] = *dm;[/code] everything works perfectly fine except of course none of the data is in the vector. What am I doing wrong? I am not sure how the index would be out of range.
[QUOTE=daigennki;52152245]I have this C++ code to obtain all the available video resolutions for my game: [code] cout << "Obtaining available display modes..." << endl; int *index = new int; SDL_DisplayMode *dm = new SDL_DisplayMode; for ((*index) = 0; (*index) < SDL_GetNumDisplayModes(0); (*index)++) { result = SDL_GetDisplayMode(0, *index, dm); if (result < 0) { logError(SDL_GetError()); return 3; } availDM[*index] = *dm; cout << "Registered display mode " << dm->w << "x" << dm->h << "@" << dm->refresh_rate << "Hz" << endl; } delete dm; delete index;[/code] Compiles successfully, but running it gives me this: [t]http://i.imgur.com/xdGakXi.png[/t] As soon as I remove the line [code]availDM[*index] = *dm;[/code] everything works perfectly fine except of course none of the data is in the vector. What am I doing wrong? I am not sure how the index would be out of range.[/QUOTE] Where do you allocate [I]availDM[/I]? The error aside, you can rewrite your code to mostly use the stack instead of heap instances: [code] cout << "Obtaining available display modes..." << endl; for (int index = 0; index < SDL_GetNumDisplayModes(0); index++) // Consider not retrieving the count from scratch each iteration. { SDL_DisplayMode dm; int result = SDL_GetDisplayMode(0, index, &dm); // I personally would make this result variable as local as possible, even if _may_ take a little more memory. if (result < 0) { logError(SDL_GetError()); return 3; } availDM[index] = dm; cout << "Registered display mode " << dm.w << "x" << dm.h << "@" << dm.refresh_rate << "Hz" << endl; }[/code] (Take everything with a grain of salt since I don't actually use C++.)
[QUOTE=Tamschi;52152408]Where do you allocate [I]availDM[/I]? The error aside, you can rewrite your code to mostly use the stack instead of heap instances: [code] cout << "Obtaining available display modes..." << endl; for (int index = 0; index < SDL_GetNumDisplayModes(0); index++) // Consider not retrieving the count from scratch each iteration. { SDL_DisplayMode dm; int result = SDL_GetDisplayMode(0, index, &dm); // I personally would make this result variable as local as possible, even if _may_ take a little more memory. if (result < 0) { logError(SDL_GetError()); return 3; } availDM[index] = dm; cout << "Registered display mode " << dm.w << "x" << dm.h << "@" << dm.refresh_rate << "Hz" << endl; }[/code] (Take everything with a grain of salt since I don't actually use C++.)[/QUOTE] "availDM" is simply declared in an included header file like this: [code]vector<SDL_DisplayMode> availDM;[/code] Am I doing it wrong? Also yes I guess I am being too careful about memory management, using stack instead does make the code cleaner and a quick search says it does not affect memory usage. Thanks for pointing that out. [editline]26th April 2017[/editline] Holy shit I am doing it wrong alright, I never resize the vector... Be right back, will do that. [editline]26th April 2017[/editline] Yeah, I forgot to resize the vector, of course that would not work... Added [code]availDM.resize(SDL_GetNumDisplayModes(0));[/code] just before the for loop, works perfectly now. I look like an idiot now... Thanks anyhow. :pcrepair: [editline]26th April 2017[/editline] I should probably point out that vector.push_back(something) seems to automatically resize the vector too.
[QUOTE=daigennki;52152544] I should probably point out that vector.push_back(something) seems to automatically resize the vector too.[/QUOTE] That is correct, since push_back adds the element to the vector, and assigning via the indexing operator requires an element to already be present at the index specified.
[QUOTE=BooTs;52146981]In my UNIX class we are supposed to write a command interpreter using the UNIX Standard Library functions fork(), wait() and exec(). The program will prompt the user for a command with arguments to execute. Ex: ls -l. Where ls is the command and -l is the argument. This is the output required: [CODE]% ./z123456 Enter command: mkdir one Enter command: touch one/file one/other one/more Enter command: ls -l one total 0 -rw-r--r-- 1 student student 0 Apr 3 13:03 file -rw-r--r-- 1 student student 0 Apr 3 13:03 more -rw-r--r-- 1 student student 0 Apr 3 13:03 other Enter command: gobly gook gobly: No such file or directory Enter command: cd one cd: No such file or directory Enter command: exit %[/CODE] The issue is that the instructor says it can take up to 4 arguments. I am not sure how to do this. The exec function takes an array of c strings as an argument but not of strings. Basically, what I am asking is. How do I recreate the argc, argv[] that the main function holds as parameters. I tried to do a for loop and use cin to add each argument to an array of strings but I am not sure how to convert those strings into C strings and the exec function complains when I try to use it. Thanks in advance.[/QUOTE] I sort of figured it out. [CODE]cout << "Enter a command: "; char s[256]; cin.getline(s, 256); char* token = strtok(s, " "); int i = 0; command = token; while (token) { if (i > 4) break; argv[i] = token; token = strtok(NULL, " "); i++; }[/CODE] I used getline to retrieve the string that was input by the user then used string tokens to split it up. Saved the first into a string called command and the rest into the argv parameter passed by main. It seems to have worked. If there is a better way to do this I am very curious.
[QUOTE=daigennki;52152544]"availDM" is simply declared in an included header file like this: [code]vector<SDL_DisplayMode> availDM;[/code] Am I doing it wrong? Also yes I guess I am being too careful about memory management, using stack instead does make the code cleaner and a quick search says it does not affect memory usage. Thanks for pointing that out. [editline]26th April 2017[/editline] Holy shit I am doing it wrong alright, I never resize the vector... Be right back, will do that. [editline]26th April 2017[/editline] Yeah, I forgot to resize the vector, of course that would not work... Added [code]availDM.resize(SDL_GetNumDisplayModes(0));[/code] just before the for loop, works perfectly now. I look like an idiot now... Thanks anyhow. :pcrepair: [editline]26th April 2017[/editline] I should probably point out that vector.push_back(something) seems to automatically resize the vector too.[/QUOTE] Number of things: - If you have "using namespace std;" somewhere, you should really remove this and avoid doing this in a header file. its more okay to have using declarations in a source file, but having them in a header file is bad practice and "using namespace std;" is especially so. - std::vector's are containers that work entirely unlike C-style arrays in many ways. Example: [cpp] std::vector<SDL_DisplayMode> availDM; // reserve pre-allocates space but doesn't initialize elements: you can't index through the vector after using reserve() availDM.reserve(SDL_GetNumDisplayModes(0)); // resize allocates space and zero-initializes elements. in this case, you can index through the vector after using resize() availDM.resize(SDL_GetNumDisplayModes(0)); [/cpp] - push_back() adds an element to the end, increasing the capacity of the vector as required. Increasing the capacity of the vector can be expensive though, and gets more expensive the more frequently it is done (as the expansion tries to work on a somewhat clever curve that over-allocates a bit). Using std::vector<>.reserve() is always a good idea, and reserve() still works nicely with push_back() - Move semantics and using std::move gets a bit advanced for what seems to be a C++ beginner, but you can use vector.push_back(std::move([element to insert])). There's a good chance the compiler is doing that anyways, but std::move like this says "construct a new display mode, but move the data inside it from the loop-constructed display mode to the display mode we're putting in the vector". It avoids a copy, and you don't need the data in the loop-constructed display mode after its put into the vector anyways. How well-read are you about C++? Something like the C++ Primer would be really helpful for you, I imagine. No need to buy the physical book too, plenty of ways (yohohoho) to acquire a PDF copy of the book. I say this as someone who did a lot of things like what you're doing when i first started using C++, because my only experience programming was with C and Python. That was unfortunate, because C++ has a lot of great features that can make your life easier but there's a tremendous amount of shitty C++ resources out there that preach vastly deprecated methods. Here's how I'd write what you did: [cpp] std::cout << "Obtaining available display modes..." << std::endl; const int num_display_modes = SDL_GetNumDisplayModes(0); std::vector<SDL_DisplayMode> availDM; availDM.reserve(num_display_modes); // for somewhat complex reasons, try to use ++(item) instead of (item)++ in for loops. // not a big deal, but its a small & simple improvement that's easy to get used to for (int index = 0; index < num_display_modes; ++index) { SDL_DisplayMode dm; int result = SDL_GetDisplayMode(0, index, &dm); if (result < 0) { logError(SDL_GetError()); return 3; } // since we move the display mode, dm would print invalid data if we called std::cout w/ it after adding it to the vector. std::cout << "Registered display mode " << dm.w << "x" << dm.h << "@" << dm.refresh_rate << "Hz" << std::endl; availDM.push_back(std::move(dm)); }[/cpp] Another quick tweak: if you specify a number in the constructor of a std::vector, that works like a call to resize - so you can use C-style array indexing. [cpp] std::cout << "Obtaining available display modes..." << std::endl; const int num_display_modes = SDL_GetNumDisplayModes(0); std::vector<SDL_DisplayMode> availDM(num_display_modes); for (int index = 0; index < num_display_modes; ++index) { SDL_DisplayMode dm; int result = SDL_GetDisplayMode(0, index, &dm); // I personally would make this result variable as local as possible, even if _may_ take a little more memory. if (result < 0) { logError(SDL_GetError()); return 3; } // since we move the display mode, dm would print invalid data if we called std::cout w/ it after adding it to the vector. std::cout << "Registered display mode " << dm.w << "x" << dm.h << "@" << dm.refresh_rate << "Hz" << std::endl; availDM[index] = std::move(dm); }[/cpp] As someone who loves C++ very much but had a rocky start with it and still fights bad habits I picked up during this start: some reading from a modern C++ textbook would be very helpful. I recommend C++ Primer (5th edition) because while it lacks C++14 info it at least covers C++11 fairly well and has pretty useful practice exercises along with healthy dollops of source code. Effective C++ by Scott Meyers is a bit more advanced and might not be immediately useful to you, but it covers lots of C++14 stuff and I still try to open it every now and then to pick up something new (or solidify a topic I've already learned a bit). [editline]edited[/editline] speaking of std::vector though, I just found out that std::vector.clear() doesn't actually free any memory or anything, just zeroes the elements. std::vector.shrink_to_fit() then actually frees memory, since it assumes all the zeroed elements aren't needed and it frees the memory required. I actually noticed this change in some of my code at work, and really noticed it in my CUDA Noise library - I had a scenario where I had a couple of buffers of image/pixel data, and I had just used clear() on them. given the size of the images I was using, using shrink_to_fit() caused RAM usage to drop up to a couple hundred MB at times! :o I only picked this up recently because of a post by /u/STL on /r/cpp too, and it seems like its something lots of people didn't know about. I would be unsurprised to find out I'm wrong though.
[QUOTE=paindoc;52153288]Number of things: - If you have "using namespace std;" somewhere, you should really remove this and avoid doing this in a header file. its more okay to have using declarations in a source file, but having them in a header file is bad practice and "using namespace std;" is especially so. - std::vector's are containers that work entirely unlike C-style arrays in many ways. Example: [cpp] std::vector<SDL_DisplayMode> availDM; // reserve pre-allocates space but doesn't initialize elements: you can't index through the vector after using reserve() availDM.reserve(SDL_GetNumDisplayModes(0)); // resize allocates space and zero-initializes elements. in this case, you can index through the vector after using resize() availDM.resize(SDL_GetNumDisplayModes(0)); [/cpp] - push_back() adds an element to the end, increasing the capacity of the vector as required. Increasing the capacity of the vector can be expensive though, and gets more expensive the more frequently it is done (as the expansion tries to work on a somewhat clever curve that over-allocates a bit). Using std::vector<>.reserve() is always a good idea, and reserve() still works nicely with push_back() - Move semantics and using std::move gets a bit advanced for what seems to be a C++ beginner, but you can use vector.push_back(std::move([element to insert])). There's a good chance the compiler is doing that anyways, but std::move like this says "construct a new display mode, but move the data inside it from the loop-constructed display mode to the display mode we're putting in the vector". It avoids a copy, and you don't need the data in the loop-constructed display mode after its put into the vector anyways. How well-read are you about C++? Something like the C++ Primer would be really helpful for you, I imagine. No need to buy the physical book too, plenty of ways (yohohoho) to acquire a PDF copy of the book. I say this as someone who did a lot of things like what you're doing when i first started using C++, because my only experience programming was with C and Python. That was unfortunate, because C++ has a lot of great features that can make your life easier but there's a tremendous amount of shitty C++ resources out there that preach vastly deprecated methods. Here's how I'd write what you did: [cpp] std::cout << "Obtaining available display modes..." << std::endl; const int num_display_modes = SDL_GetNumDisplayModes(0); std::vector<SDL_DisplayMode> availDM; availDM.reserve(num_display_modes); // for somewhat complex reasons, try to use ++(item) instead of (item)++ in for loops. // not a big deal, but its a small & simple improvement that's easy to get used to for (int index = 0; index < num_display_modes; ++index) { SDL_DisplayMode dm; int result = SDL_GetDisplayMode(0, index, &dm); if (result < 0) { logError(SDL_GetError()); return 3; } // since we move the display mode, dm would print invalid data if we called std::cout w/ it after adding it to the vector. std::cout << "Registered display mode " << dm.w << "x" << dm.h << "@" << dm.refresh_rate << "Hz" << std::endl; availDM.push_back(std::move(dm)); }[/cpp] Another quick tweak: if you specify a number in the constructor of a std::vector, that works like a call to resize - so you can use C-style array indexing. [cpp] std::cout << "Obtaining available display modes..." << std::endl; const int num_display_modes = SDL_GetNumDisplayModes(0); std::vector<SDL_DisplayMode> availDM(num_display_modes); for (int index = 0; index < num_display_modes; ++index) { SDL_DisplayMode dm; int result = SDL_GetDisplayMode(0, index, &dm); // I personally would make this result variable as local as possible, even if _may_ take a little more memory. if (result < 0) { logError(SDL_GetError()); return 3; } // since we move the display mode, dm would print invalid data if we called std::cout w/ it after adding it to the vector. std::cout << "Registered display mode " << dm.w << "x" << dm.h << "@" << dm.refresh_rate << "Hz" << std::endl; availDM[index] = std::move(dm); }[/cpp] As someone who loves C++ very much but had a rocky start with it and still fights bad habits I picked up during this start: some reading from a modern C++ textbook would be very helpful. I recommend C++ Primer (5th edition) because while it lacks C++14 info it at least covers C++11 fairly well and has pretty useful practice exercises along with healthy dollops of source code. Effective C++ by Scott Meyers is a bit more advanced and might not be immediately useful to you, but it covers lots of C++14 stuff and I still try to open it every now and then to pick up something new (or solidify a topic I've already learned a bit). [editline]edited[/editline] speaking of std::vector though, I just found out that std::vector.clear() doesn't actually free any memory or anything, just zeroes the elements. std::vector.shrink_to_fit() then actually frees memory, since it assumes all the zeroed elements aren't needed and it frees the memory required. I actually noticed this change in some of my code at work, and really noticed it in my CUDA Noise library - I had a scenario where I had a couple of buffers of image/pixel data, and I had just used clear() on them. given the size of the images I was using, using shrink_to_fit() caused RAM usage to drop up to a couple hundred MB at times! :o I only picked this up recently because of a post by /u/STL on /r/cpp too, and it seems like its something lots of people didn't know about. I would be unsurprised to find out I'm wrong though.[/QUOTE] Holy shit, I did not even ask but this is all extremely useful. I will keep those tips in mind. Thank you! [editline]27th April 2017[/editline] Another question. I use boost's property trees to load configurations from files. As soon as I implemented it, I did not get any errors but I did get memory leaks up the ass: [code]Detected memory leaks! Dumping objects -> [...] {863} normal block at 0x0067EBB0, 80 bytes long. Data: <H h load_save > 48 11 68 00 6C 6F 61 64 5F 73 61 76 65 00 CD CD {851} normal block at 0x006800D0, 32 bytes long. Data: < > E3 82 BB E3 83 BC E3 83 96 E3 83 87 E3 83 BC E3 {850} normal block at 0x0067F230, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {849} normal block at 0x00681C50, 16 bytes long. Data: < 0 g > CD CD CD CD 30 F2 67 00 CD CD CD CD 00 00 00 00 {848} normal block at 0x006811B8, 8 bytes long. Data: < g > CC EE 67 00 00 00 00 00 {847} normal block at 0x00681180, 8 bytes long. Data: < g > B0 EE 67 00 00 00 00 00 {846} normal block at 0x0067EEB0, 80 bytes long. Data: < h save_3 > 80 11 68 00 73 61 76 65 5F 33 00 CD CD CD CD CD {834} normal block at 0x0067FD60, 32 bytes long. Data: < > E3 82 BB E3 83 BC E3 83 96 E3 83 87 E3 83 BC E3 {833} normal block at 0x0067F1B0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {832} normal block at 0x00673778, 16 bytes long. Data: < g > CD CD CD CD B0 F1 67 00 CD CD CD CD 00 00 00 00 {831} normal block at 0x00680CE8, 8 bytes long. Data: <L g > 4C EA 67 00 00 00 00 00 {830} normal block at 0x00680CB0, 8 bytes long. Data: <0 g > 30 EA 67 00 00 00 00 00 {829} normal block at 0x0067EA30, 80 bytes long. Data: < h save_2 > B0 0C 68 00 73 61 76 65 5F 32 00 CD CD CD CD CD {817} normal block at 0x0067FCC0, 32 bytes long. Data: < > E3 82 BB E3 83 BC E3 83 96 E3 83 87 E3 83 BC E3 {816} normal block at 0x0067E930, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {815} normal block at 0x00663308, 16 bytes long. Data: < 0 g > CD CD CD CD 30 E9 67 00 CD CD CD CD 00 00 00 00 {814} normal block at 0x00680B60, 8 bytes long. Data: <L g > 4C F1 67 00 00 00 00 00 {813} normal block at 0x00680AF0, 8 bytes long. Data: <0 g > 30 F1 67 00 00 00 00 00 {812} normal block at 0x0067F130, 80 bytes long. Data: < h save_1 > F0 0A 68 00 73 61 76 65 5F 31 00 CD CD CD CD CD {800} normal block at 0x0067F0B0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {799} normal block at 0x00673478, 16 bytes long. Data: < g > CD CD CD CD B0 F0 67 00 CD CD CD CD 00 00 00 00 {798} normal block at 0x00681030, 8 bytes long. Data: <L g > 4C E7 67 00 00 00 00 00 {797} normal block at 0x00681110, 8 bytes long. Data: <0 g > 30 E7 67 00 00 00 00 00 {796} normal block at 0x0067E730, 80 bytes long. Data: < h load_game > 10 11 68 00 6C 6F 61 64 5F 67 61 6D 65 00 CD CD {784} normal block at 0x0067ED30, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {783} normal block at 0x00663088, 16 bytes long. Data: < 0 g > CD CD CD CD 30 ED 67 00 CD CD CD CD 00 00 00 00 {782} normal block at 0x00680DC8, 8 bytes long. Data: <L g > 4C EE 67 00 00 00 00 00 {781} normal block at 0x00680BD0, 8 bytes long. Data: <0 g > 30 EE 67 00 00 00 00 00 {780} normal block at 0x0067EE30, 80 bytes long. Data: < h new_game > D0 0B 68 00 6E 65 77 5F 67 61 6D 65 00 CD CD CD {768} normal block at 0x0067F2B0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {767} normal block at 0x00662F88, 16 bytes long. Data: < g > CD CD CD CD B0 F2 67 00 CD CD CD CD 1E 00 00 00 {766} normal block at 0x00680FF8, 8 bytes long. Data: <L g > 4C EB 67 00 00 00 00 00 {765} normal block at 0x00680C08, 8 bytes long. Data: <0 g > 30 EB 67 00 00 00 00 00 {764} normal block at 0x0067EB30, 80 bytes long. Data: < h ja-JP > 08 0C 68 00 6A 61 2D 4A 50 00 CD CD CD CD CD CD {752} normal block at 0x0067E7B0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {751} normal block at 0x00663288, 16 bytes long. Data: < g > CD CD CD CD B0 E7 67 00 CD CD CD CD 00 00 00 00 {750} normal block at 0x006810A0, 8 bytes long. Data: < g > CC F4 67 00 00 00 00 00 {749} normal block at 0x00681068, 8 bytes long. Data: < g > B0 F4 67 00 00 00 00 00 {748} normal block at 0x0067F4B0, 80 bytes long. Data: <h h go_back > 68 10 68 00 67 6F 5F 62 61 63 6B 00 CD CD CD CD [...] {480} normal block at 0x0067DFB0, 80 bytes long. Data: < g options_appl> D0 F8 67 00 6F 70 74 69 6F 6E 73 5F 61 70 70 6C {468} normal block at 0x0067D830, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {467} normal block at 0x00662D48, 16 bytes long. Data: < 0 g > CD CD CD CD 30 D8 67 00 CD CD CD CD 00 00 00 00 {466} normal block at 0x0067BC18, 8 bytes long. Data: <L g > 4C DD 67 00 00 00 00 00 {465} normal block at 0x0067BAC8, 8 bytes long. Data: <0 g > 30 DD 67 00 00 00 00 00 {464} normal block at 0x0067DD30, 80 bytes long. Data: < g game_options> C8 BA 67 00 67 61 6D 65 5F 6F 70 74 69 6F 6E 73 {452} normal block at 0x00672068, 32 bytes long. Data: <Delete this save> 44 65 6C 65 74 65 20 74 68 69 73 20 73 61 76 65 {451} normal block at 0x0067DEB0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {450} normal block at 0x00663148, 16 bytes long. Data: < g > CD CD CD CD B0 DE 67 00 CD CD CD CD 00 00 00 00 {449} normal block at 0x0067D418, 8 bytes long. Data: <L g > 4C DE 67 00 00 00 00 00 {448} normal block at 0x006720B8, 32 bytes long. Data: <delete_save_warn> 64 65 6C 65 74 65 5F 73 61 76 65 5F 77 61 72 6E {447} normal block at 0x0067D3E0, 8 bytes long. Data: <0 g > 30 DE 67 00 00 00 00 00 {446} normal block at 0x0067DE30, 80 bytes long. Data: < g g > E0 D3 67 00 B8 20 67 00 CD CD CD CD CD CD CD CD {433} normal block at 0x0067E2B0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {432} normal block at 0x00663488, 16 bytes long. Data: < g > CD CD CD CD B0 E2 67 00 CD CD CD CD 00 00 00 00 {431} normal block at 0x0067BBE0, 8 bytes long. Data: < e > FC CB 65 00 00 00 00 00 {430} normal block at 0x0067D258, 8 bytes long. Data: < e > E0 CB 65 00 00 00 00 00 {429} normal block at 0x0065CBE0, 80 bytes long. Data: <X g delete_save > 58 D2 67 00 64 65 6C 65 74 65 5F 73 61 76 65 00 {417} normal block at 0x006721A8, 32 bytes long. Data: <Overwrite this s> 4F 76 65 72 77 72 69 74 65 20 74 68 69 73 20 73 {416} normal block at 0x0065CDE0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {415} normal block at 0x00663388, 16 bytes long. Data: < e > CD CD CD CD E0 CD 65 00 CD CD CD CD 00 00 00 00 {414} normal block at 0x0067D488, 8 bytes long. Data: <| e > 7C CD 65 00 00 00 00 00 {413} normal block at 0x00672568, 32 bytes long. Data: <overwrite_save_w> 6F 76 65 72 77 72 69 74 65 5F 73 61 76 65 5F 77 {412} normal block at 0x0067D450, 8 bytes long. Data: <` e > 60 CD 65 00 00 00 00 00 {411} normal block at 0x0065CD60, 80 bytes long. Data: <P g h%g > 50 D4 67 00 68 25 67 00 CD CD CD CD CD CD CD CD {397} normal block at 0x00652078, 48 bytes long. Data: <Please select sa> 50 6C 65 61 73 65 20 73 65 6C 65 63 74 20 73 61 {395} normal block at 0x0065CCE0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {394} normal block at 0x00663108, 16 bytes long. Data: < e > CD CD CD CD E0 CC 65 00 CD CD CD CD 00 00 00 00 {393} normal block at 0x0067D5A0, 8 bytes long. Data: <| e > 7C CF 65 00 00 00 00 00 {392} normal block at 0x0067D290, 8 bytes long. Data: <` e > 60 CF 65 00 00 00 00 00 {391} normal block at 0x0065CF60, 80 bytes long. Data: < g paste_save_d> 90 D2 67 00 70 61 73 74 65 5F 73 61 76 65 5F 64 {379} normal block at 0x006621E8, 48 bytes long. Data: <Please select sa> 50 6C 65 61 73 65 20 73 65 6C 65 63 74 20 73 61 {377} normal block at 0x0065CAE0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {376} normal block at 0x006631C8, 16 bytes long. Data: < e > CD CD CD CD E0 CA 65 00 CD CD CD CD 00 00 00 00 {375} normal block at 0x0067D338, 8 bytes long. Data: < e > FC D3 65 00 00 00 00 00 {374} normal block at 0x0067D300, 8 bytes long. Data: < e > E0 D3 65 00 00 00 00 00 {373} normal block at 0x0065D3E0, 80 bytes long. Data: < g copy_save_de> 00 D3 67 00 63 6F 70 79 5F 73 61 76 65 5F 64 65 {361} normal block at 0x0065C7E0, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {360} normal block at 0x00663008, 16 bytes long. Data: < e > CD CD CD CD E0 C7 65 00 CD CD CD CD 00 00 00 00 {359} normal block at 0x0067D370, 8 bytes long. Data: <| e > 7C D5 65 00 00 00 00 00 {358} normal block at 0x0067D220, 8 bytes long. Data: <` e > 60 D5 65 00 00 00 00 00 {357} normal block at 0x0065D560, 80 bytes long. Data: < g copy_save > 20 D2 67 00 63 6F 70 79 5F 73 61 76 65 00 CD CD {345} normal block at 0x0065C860, 80 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {344} normal block at 0x006630C8, 16 bytes long. Data: < ` e > CD CD CD CD 60 C8 65 00 CD CD CD CD 00 00 00 00 {343} normal block at 0x0067D568, 8 bytes long. Data: <| e > 7C D3 65 00 00 00 00 00 {342} normal block at 0x0067D4F8, 8 bytes long. Data: <` e > 60 D3 65 00 00 00 00 00 {341} normal block at 0x0065D360, 80 bytes long. Data: < g load_save > F8 D4 67 00 6C 6F 61 64 5F 73 61 76 65 00 CD CD [...] Object dump complete.[/code] There are acutally many more lines to that memory dump, these here are just ones that show some strings which are present in the JSON file. Am I forgetting to do something like free memory somewhere?
[QUOTE=paindoc;52153288] speaking of std::vector though, I just found out that std::vector.clear() doesn't actually free any memory or anything, just zeroes the elements. std::vector.shrink_to_fit() then actually frees memory, since it assumes all the zeroed elements aren't needed and it frees the memory required. I actually noticed this change in some of my code at work, and really noticed it in my CUDA Noise library - I had a scenario where I had a couple of buffers of image/pixel data, and I had just used clear() on them. given the size of the images I was using, using shrink_to_fit() caused RAM usage to drop up to a couple hundred MB at times! :o I only picked this up recently because of a post by /u/STL on /r/cpp too, and it seems like its something lots of people didn't know about. I would be unsurprised to find out I'm wrong though.[/QUOTE] I actually thought the standard guaranteed the behaviour you're describing but it seems it doesn't, it just doesn't guarantee reallocation / capacity change. I sure hope all implementations do it the same way (the way you describe) because that's the only behaviour that makes sense to me - take the use case of a function that takes in a vector by reference as a return container like this: [CODE] void GetAllRedWorldObjects(World* world, std::vector<WorldObject>& out) { out.clear(); for(auto& wo : world->GetObjects()) { if(wo.IsRed()) { out.emplace_back(wo); } } } [/CODE] It makes sense to call clear() on the out vector in that function to make sure it only contains the output of that function (let's just assume we want that instead of appending to the existing contents). However, you'll also want to reserve() on out before filling it with the results, doing so within the function though requires the function writer to assume a reserve strategy - should reserve() be called with the total number of objects in the world to make sure the worst case fits? Probably, but what if not? This is a bad example probably, but the point I'm trying to make is, I can think of a lot of cases where I want to clear() on a vector inside a function, but leave it up to the callee to reserve memory for the vector. If clear() freed the memory inside the vector, I couldn't do that because I could not call reserve() before a clear(). The way I think of it is this, std::vector has two layers of bookkeeping, one layer for the stored elements and one for the actual memory. This is why there's resize() and reserve(), and it makes a lot of sense to me at least to have clear() and shrink_to_fit() as the equivalent for each layer. [editline]27th April 2017[/editline] [QUOTE=daigennki;52152544] Also yes I guess I am being too careful about memory management, using stack instead does make the code cleaner and a quick search says it does not affect memory usage. Thanks for pointing that out. [/QUOTE] Also, though paindoc et al. already went over everything important very concisely, this in particular I thought worth picking up again real quick: You were actually going in a VERY dangerous direction there. ALWAYS prefer stack memory - stack allocation is WAY more lightweight than heap allocation (allocating stuff via new / malloc), ESPECIALLY for small types like, say, int. Just for some perspective, allocating an integer on the heap will allocate both the 4 bytes required to store that int AND 4 MORE bytes alongside that because it has to store the allocation size to know how much to free when you call delete / free on it. That's TWICE the memory you'd need. Stack allocation doesn't need to store additional information. Also stack allocation internally just bumps a pointer or an offset and there's the memory, versus the heap allocator going crazy with very advanced algorithms to allow for fast general purpose allocation. While it IS fast, it can't possibly as fast as stack allocation except for in idealised situations that you usually don't end up in a lot. Again, kicking all that overhead off for a tiny integer is a really really bad habit. In general, it's good advice to prefer the stack unless you have a type that's a) just too big for the stack (because stack memory IS limited) or b) NEEDS to be on the heap for some other reason (lifetime should extend scope for example). Just wanted to re-stress this because I think it's immensly important. EDIT: Oh yeah and obviously you can easily forget to delete something so stack allocation is considered safer because it automates deallocation. EDITEDIT: That in mind, could you show the code that potentially leads to the crazy leakage?
[QUOTE=JWki;52156123]Also, though paindoc et al. already went over everything important very concisely, this in particular I thought worth picking up again real quick: You were actually going in a VERY dangerous direction there. ALWAYS prefer stack memory - stack allocation is WAY more lightweight than heap allocation (allocating stuff via new / malloc), ESPECIALLY for small types like, say, int. Just for some perspective, allocating an integer on the heap will allocate both the 4 bytes required to store that int AND 4 MORE bytes alongside that because it has to store the allocation size to know how much to free when you call delete / free on it. That's TWICE the memory you'd need. Stack allocation doesn't need to store additional information. Also stack allocation internally just bumps a pointer or an offset and there's the memory, versus the heap allocator going crazy with very advanced algorithms to allow for fast general purpose allocation. While it IS fast, it can't possibly as fast as stack allocation except for in idealised situations that you usually don't end up in a lot. Again, kicking all that overhead off for a tiny integer is a really really bad habit. In general, it's good advice to prefer the stack unless you have a type that's a) just too big for the stack (because stack memory IS limited) or b) NEEDS to be on the heap for some other reason (lifetime should extend scope for example). Just wanted to re-stress this because I think it's immensly important. EDIT: Oh yeah and obviously you can easily forget to delete something so stack allocation is considered safer because it automates deallocation. EDITEDIT: That in mind, could you show the code that potentially leads to the crazy leakage?[/QUOTE] Figured. Heap allocation does make code messy too... And yes, as soon as I disable (comment) this code [code] int loadLocalization() { logError("Loading localization...", ERROR_TYPE_INFO); try { bpt::read_json("localization.json", lcRoot); } catch (std::exception const& exception) { logError(exception.what()); return 1; } return 0; } string localize(string key) { try { return lcRoot.get<string>(lang + '.' + key); } catch(std::exception const& exception) { logError(exception.what()); return "_LCERROR_"; } }[/code] and this code [code]namespace bpt = boost::property_tree; bpt::ptree cfgRoot; int loadConfig() { logError("Loading configuration file...", ERROR_TYPE_INFO); try { bpt::read_json("game.cfg", cfgRoot); } catch (std::exception const& exception) { logError(exception.what()); return 1; } return 0; }[/code] the leakage seems to stop.
[QUOTE=JWki;52156123]I actually thought the standard guaranteed the behaviour you're describing but it seems it doesn't, it just doesn't guarantee reallocation / capacity change. I sure hope all implementations do it the same way (the way you describe) because that's the only behaviour that makes sense to me - take the use case of a function that takes in a vector by reference as a return container like this: [CODE] void GetAllRedWorldObjects(World* world, std::vector<WorldObject>& out) { out.clear(); for(auto& wo : world->GetObjects()) { if(wo.IsRed()) { out.emplace_back(wo); } } } [/CODE] It makes sense to call clear() on the out vector in that function to make sure it only contains the output of that function (let's just assume we want that instead of appending to the existing contents). However, you'll also want to reserve() on out before filling it with the results, doing so within the function though requires the function writer to assume a reserve strategy - should reserve() be called with the total number of objects in the world to make sure the worst case fits? Probably, but what if not? This is a bad example probably, but the point I'm trying to make is, I can think of a lot of cases where I want to clear() on a vector inside a function, but leave it up to the callee to reserve memory for the vector. If clear() freed the memory inside the vector, I couldn't do that because I could not call reserve() before a clear(). The way I think of it is this, std::vector has two layers of bookkeeping, one layer for the stored elements and one for the actual memory. This is why there's resize() and reserve(), and it makes a lot of sense to me at least to have clear() and shrink_to_fit() as the equivalent for each layer. [editline]27th April 2017[/editline] Also, though paindoc et al. already went over everything important very concisely, this in particular I thought worth picking up again real quick: You were actually going in a VERY dangerous direction there. ALWAYS prefer stack memory - stack allocation is WAY more lightweight than heap allocation (allocating stuff via new / malloc), ESPECIALLY for small types like, say, int. Just for some perspective, allocating an integer on the heap will allocate both the 4 bytes required to store that int AND 4 MORE bytes alongside that because it has to store the allocation size to know how much to free when you call delete / free on it. That's TWICE the memory you'd need. Stack allocation doesn't need to store additional information. Also stack allocation internally just bumps a pointer or an offset and there's the memory, versus the heap allocator going crazy with very advanced algorithms to allow for fast general purpose allocation. While it IS fast, it can't possibly as fast as stack allocation except for in idealised situations that you usually don't end up in a lot. Again, kicking all that overhead off for a tiny integer is a really really bad habit. In general, it's good advice to prefer the stack unless you have a type that's a) just too big for the stack (because stack memory IS limited) or b) NEEDS to be on the heap for some other reason (lifetime should extend scope for example). Just wanted to re-stress this because I think it's immensly important. EDIT: Oh yeah and obviously you can easily forget to delete something so stack allocation is considered safer because it automates deallocation. EDITEDIT: That in mind, could you show the code that potentially leads to the crazy leakage?[/QUOTE] I agree, I appreciate the behavior being split between clear() and shrink_to_fit(). I just wish it was more common knowledge that you should combine the two to actually free memory - I see several instances in open-source projects on github where someone says "clear the vector to save memory", and they only ever use clear(). Sometimes this happens in rather expensive algorithms, too. As far as how implemented it is, I know for a fact its what MSVC uses but thats it. afaik, the rest of the implementations all do this as well and MSVC was the last one to have std::vector reach full compliance to the C++14 standard (iirc, might've been C++11). Mostly due to a shitload of work from /u/STL, as I understood it. [QUOTE=daigennki;52156515]Figured. Heap allocation does make code messy too... And yes, as soon as I disable (comment) this code [code] int loadLocalization() { logError("Loading localization...", ERROR_TYPE_INFO); try { bpt::read_json("localization.json", lcRoot); } catch (std::exception const& exception) { logError(exception.what()); return 1; } return 0; } string localize(string key) { try { return lcRoot.get<string>(lang + '.' + key); } catch(std::exception const& exception) { logError(exception.what()); return "_LCERROR_"; } }[/code] and this code [code]namespace bpt = boost::property_tree; bpt::ptree cfgRoot; int loadConfig() { logError("Loading configuration file...", ERROR_TYPE_INFO); try { bpt::read_json("game.cfg", cfgRoot); } catch (std::exception const& exception) { logError(exception.what()); return 1; } return 0; }[/code] the leakage seems to stop.[/QUOTE] If an exception is thrown, the destructor of the relevant class won't get called in the case of items allocated with "new" and such, but I'm not sure what's going on here. I feel like there's some other odd behavior with try/catch blocks that I'm forgetting, but I can't think of it right now. I'm not really sure why boost stuff would cause leaks though, since Boost is usually pretty solidly engineered. also, looks you still have "using namespace std;" somewhere, based on the "string" vs "std::string" in that code. The main reason I bring that up is that namespace conflicts can be a bitch that cause really bizarre bugs, and Boost is [I]especially[/I] an example of when "using namespace std;" can be dangerous because there are several components of boost that have the same names as standard library components. I'd try debugging the functions here step-by-step and seeing where memory is allocated and deallocated, and I'd also try using Ctrl-F or w/e to find an obliterate "using namespace std;" in case it happens to be causing a problem (and I had similarly odd bugs in one of my earliest projects because of the very same, so I've done it too lol)
[QUOTE=paindoc;52157169]I agree, I appreciate the behavior being split between clear() and shrink_to_fit(). I just wish it was more common knowledge that you should combine the two to actually free memory - I see several instances in open-source projects on github where someone says "clear the vector to save memory", and they only ever use clear(). Sometimes this happens in rather expensive algorithms, too. As far as how implemented it is, I know for a fact its what MSVC uses but thats it. afaik, the rest of the implementations all do this as well and MSVC was the last one to have std::vector reach full compliance to the C++14 standard (iirc, might've been C++11). Mostly due to a shitload of work from /u/STL, as I understood it. If an exception is thrown, the destructor of the relevant class won't get called in the case of items allocated with "new" and such, but I'm not sure what's going on here. I feel like there's some other odd behavior with try/catch blocks that I'm forgetting, but I can't think of it right now. I'm not really sure why boost stuff would cause leaks though, since Boost is usually pretty solidly engineered. also, looks you still have "using namespace std;" somewhere, based on the "string" vs "std::string" in that code. The main reason I bring that up is that namespace conflicts can be a bitch that cause really bizarre bugs, and Boost is [I]especially[/I] an example of when "using namespace std;" can be dangerous because there are several components of boost that have the same names as standard library components. I'd try debugging the functions here step-by-step and seeing where memory is allocated and deallocated, and I'd also try using Ctrl-F or w/e to find an obliterate "using namespace std;" in case it happens to be causing a problem (and I had similarly odd bugs in one of my earliest projects because of the very same, so I've done it too lol)[/QUOTE] Looks like one of my header files still had "using namespace std;". Removed it and now using "std::" instead, but the memory leaks have still not been fixed at all. No exceptions thrown either. This is a weird one, I am entirely unsure how memory leaks are happening here either... [del]Should I be concerned about the performance too? I have not even gotten to 3D rendering yet and it has >15% CPU usage according to task manager, and the framerate is not even 60 fps, flying all over the place but averaging around 45 fps. Framerate seems to drop and CPU usage seems to increase whenever more 2D polygons are drawn with OpenGL, maybe my drawing functions are inefficient?[/del] Looks like I was right, drawing functions were inefficient, I was converting SDL surfaces to OpenGL textures every frame rather than just once. Made it load images as OpenGL textures from the start, now works very smoothly.
So I'm pretty much still a low level programmer, and I need some guidance right now. Currently I'm working on some kind of DnD Toolkit as a Companion Program which should help me being a Dungeon master. Nothing too complicated, I have some tabs for managing Players, Items and stuff, and an tab with some common tools, like dice rolls and so on. I'm working with Visual Studio / C# in a WPF Project. Most of the stuff is pretty easy to find out on myself. But there are some hurdles I want some guidance on before tackling them. So my programming experience pretty much ends with "simple" console projects, some pages on Project Euler and a few a little bit more advanced projects. But I never actually captured the state of my program and saved it to a file or something. So the situation is for example, I have a window to create a Player Character which creates and initializes an Instance of my object Player, same goes for Items and NPCs. The question is now, what would actually be a good way to store all this information? All the created Items, Players and so on... From my understanding I could either save all that stuff in a database, which would require me to run an sql server somewhere, which is possible, but MAYBE a bit overkill I don't know... Or I could save the stuff somewhere as an Xml file or something. I tried the Xml method and exported an instance of Player on my harddrive which worked fine. But how do I scale that up? This is where I need some guidance. Do I try to save all the Players to a single Xml file? Or should every single object instance get it's own file? Or is there a much cooler way to do all this? Are there any neat tutorials or other resources which could help me? Well lets keep it at that for now. Thanks in advance!
I don't think there's any real right answer, but if you're the only one running the program (like DM only, not the players) then maybe consider saving all the players and campaign information into a single campaign file?
Sorry, you need to Log In to post a reply to this thread.