Return array from function C++ - c++

I'm new to C++, I have experience with C#, Objective-C and JavaScript.
At the moment I'm trying to write a function that takes a path and returns a directory listing (all files and folders at that path). I'm doing this on Ubuntu.
Here's my code so far, to be honest I'm struggling to understand the double pointer syntax and what it's achieving but this is where my googling has lead me...
int FileManager::GetDirectoryListing(char *path, dirent **directoryEntries)
{
// Debug output...
printf("Listing directory at %s\n", path);
// Allocate memory for the directory entries
*directoryEntries = new dirent[MAX_FILES];
// Open the path we were provided
DIR *directory = opendir(path);
// A counter of how many entries we have read
int entryCount = 0;
// Make sure we were able to open the directory
if(directory) {
printf("Successfully opened directory\n");
// Read the first entry in the directory
struct dirent *directoryEntry = readdir(directory);
// While we have a directory entry
while(directoryEntry) {
// Debug output...
printf("%s\n", directoryEntry->d_name);
// Copy the directory entry to the array of directory entries we will return
memcpy(&directoryEntries[entryCount], directoryEntry, sizeof(struct dirent));
// Increase our counter
++entryCount;
// Read the next directory
directoryEntry = readdir(directory);
}
// Close the directory
closedir(directory);
}
return entryCount;
}
And then I call this function by:
dirent *directoryEntries = NULL;
int numberOfEntries = FileManager::GetDirectoryListing(deviceRootPath, &directoryEntries);
printf("File Manager returned directory listing.\n");
for(int i = 0; i < numberOfEntries; ++i) {
printf("Looping through directory entries, at index: %i\n", i);
printf("%s\n", directoryEntries[i].d_name);
}
It's locking up when it tries to access the first element in directoryEntries i.e. The first time around the loop.
I know I'm not understanding what the double pointer is doing and I don't have a clear picture in my head about the structure of directoryEntries after the call to GetDirectoryListing.
What is happening and what is the correct way to loop through directoryEntries?

This line
memcpy(&directoryEntries[entryCount], directoryEntry, sizeof(struct dirent));
should instead be this:
memcpy(&(*directoryEntries)[entryCount], directoryEntry, sizeof(struct dirent));
or equivalently:
memcpy(*directoryEntries + entryCount, directoryEntry, sizeof(struct dirent));
The reason is that directoryEntries is a pointer to a pointer to an array. In memory, it looks like this:
+------------+
directoryEntries --> array_head --> | dirents[0] |
+------------+
| dirents[1] |
+------------+
| dirents[2] |
+------------+
| ... |
But you're treating it like directoryEntries is a pointer to an array, which it is not:
WRONG! +------------+
directoryEntries --> | dirents[0] |
+------------+
| dirents[1] |
+------------+
| ... |
So you're writing out-of-bounds into memory you don't own, resulting in Undefined Behavior.
The reason you need an extra level of indirection is because in C, function parameters are always passed by value. In order to modify a parameter, you need to pass in a pointer to the original value, which is what you're doing. You just have to remember that when dealing with that pointer, you have an extra level of indirection.
If you're using C++ and not C, you would be much better off using a reference parameter instead of a pointer, and you should also use a std::vector<struct dirent>. You don't have the extra level of indirection to worry about, and the memory management is handled for you automatically.

*directoryEntries = new dirent[MAX_FILES];
What if the number of directories is greater than MAX_FILES? How do you know that it cannot be greater than MAX_FILES?
I think you should use std::vector<dirent> instead of dirent*. Many of the problems will be solved.
I would implement the function as:
std::vector<dirent> FileManager::GetDirectoryListing(char *path)
{
std::vector<dirent> dirs;
DIR *directory = opendir(path);
if(directory) {
struct dirent *directoryEntry = readdir(directory);
while(directoryEntry) {
dirs.push_back(*directoryEntry); //push a copy of the original!
directoryEntry = readdir(directory);
}
closedir(directory);
}
return dirs;
}
Modern compilers will most probably optimize this code, to avoiding copy of the return value. This optimization is called:
Return Value Optimization (RVO) (or Named RVO)
Also note that directories.size() will tell you the number of entries. So at call site, you can simply do this:
std::vector<dirent> dirs = FileManager::GetDirectoryListing(deviceRootPath);
for(size_t i = 0; i < dirs.size() ; ++i)
{
std::cout << dirs[i].d_name << std:endl;
}
In general, prefer std::cout over printf, as the latter is not safe!

Your mistake is in this line:
memcpy(&directoryEntries[entryCount], directoryEntry, sizeof(struct dirent));
Your directoryEntries is pointer to pointers to struct dirent. Each entry in it is a pointer to a struct dirent. Your '&' causes you to copy into the address of a pointer, which is not what you wanted. You want:
memcpy(directoryEntries[entryCount], directoryEntry, sizeof(struct dirent));

Related

char has only the last pointer

I'm putting all file names (in this case all files in the folder /Windows/Fonts/) into the char File_Names. Menawhile the names are rendered as well, but after I have put everything in the char (when while ends), I try to access it and use one of the names in something else (this happens after while), but every single pointer I try only gives the last file from the folder (this means, it only has the last pointer). How do I keep all different file names and can use them after while?
Here is a fragment from my program:
//-------------------- List files start
int File_Name_Y = Font_Window_Y+35-Mouse_Scroll*10;
char *File_Names[4096];
struct dirent *entry;
DIR *dir = opendir("/Windows/Fonts");
int t = 1;
while ((entry = readdir(dir)) != NULL)
{
t += 1;
File_Names[t] = entry->d_name;
if (File_Name_Y <= Font_Window_Y+H-65 && File_Name_Y >= Font_Window_Y+30)
{
draw_text (Font_Window_X+15, File_Name_Y, File_Names[t], {1, 1, 1}, 1.5);
}
File_Name_Y += 20;
}
closedir(dir);
//------------------ List files end
if (use_button (SelectFontButton))
{
if (Mouse_Pressed)
{
Mouse_Pressed = 0;
char Font_Path[1024];
strcpy (Font_Path, "/Windows/Fonts/");
strcat(Font_Path, File_Names[3]);
strcpy (Global_Font, Font_Path);
printf (Global_Font);
}
}
You are storing the exact same value, entry->d_name in every entry. Of course they're all going to point to the same string.
You may be thinking that readdir changes the value of entry->d_name to something different every time. But it doesn't. Every time, it sets the value of entry->d_name to point to the very same buffer that readdir uses to hold the entry name.
You need to save the actual name, not a pointer to a buffer controlled by some other piece of code. Allocating an array of pointers is insufficient -- where are the actual entry names going to be stored?

Runtime error when accessing class member in VS2015 but not on Linux

This code works OK when compiled with g++ on Linux, but when I try to execute them in VS 2015 (both debug and release) I receive runtime error. What's wrong with it?
#include "stdafx.h"
#include <string.h>
#include <iostream>
using namespace std;
struct Stru1
{
int mem;
};
struct Stru2 : public Stru1
{
char szMem1[256];
int dwMem2;
int dwMem3;
};
static void clFun(Stru1* s) {
Stru2* s2 = (Stru2*)s;
cout << s2->szMem1 << endl;//blahblah
cout << s2->dwMem2 << endl;//runtime error
}
class Temp {
public:
void callDispatch() {
simRecv->mem = 2;
Stru2* sro = (Stru2*)simRecv;
strcpy(sro->szMem1, "blahblah");
sro->dwMem2 = 11;
sro->dwMem3 = 77;
//cout << sro->szMem1 << endl;//blahblah
//cout << sro->dwMem2 << endl;//runtime error when uncommented
clFun(simRecv);
}
~Temp() { delete simRecv; }
Stru1* simRecv = new Stru1;
};
int main()
{
Temp tmp;
tmp.callDispatch();
return 0;
}
Error:
Exception thrown at 0x0000000077A0F23C (ntdll.dll) in ConsoleApplication1.exe: 0xC0000005: Access violation reading location 0x00000FB00188C508.
Stru2* sro = (Stru2*)simRecv;
simRecv is a Stru1, so your unsafe cast to Stru2 is invalid in this line.
In this line you create this Stru1,
Stru1* simRecv = new Stru1;
Here Stru1 is assigned the memory needed to create a Stru1, which is smaller than a Stru2.
By doing:
Stru2* sro = (Stru2*)simRecv;
You are just saying: I have this "thing" and treat it as a Stru2. But there hasn't been a new Stru2 created anywhere so the object just isn't there.
It is basically the same as saying
I have a large wall, but I'll treat it as a house and expect a door in it.
The reason that it might work on a different platform can be due to a different memory allocation of the platform.
As for the analogy: you might have reached the end of the wall and hence don't hurt your head, but you are not inside the house and you won't leave your wallet there.
For example, this line will eventually point to somewhere:
sro->dwMem3 = 77;
The question is: is this within valid program space? If it is, no error will occur, but that doesn't mean it is good. You are probably altering a variable, somewhere else, leading to unpredictable results.
An example:
Platform1:
| Stru1 | some variable | some other variable |
| mem | 0 | 11 |
| | | ((Stru2*) simRecv)->dwMem2 |
//no errors, but strange side effects
Platform2:
| Stru1 | some variable | some other program space |
| mem | 0 | ERROR: ACCES VIOLATION |
| | | ((Stru2*) simRecv)->dwMem2 |
//0xC0000005
If you assign a Stru2 (by actually creating it) in the first place, all will be good:
Stru1* simRecv = (Stru1*) new Stru2;
Having said that; these cast are considered unsafe (for now obvious reasons).
The alternative is to use, for example a static_cast. It will make sure you'll get a build error when trying to do something "illegal".
http://www.cplusplus.com/doc/tutorial/typecasting/
additional note about cplusplus see: What's wrong with cplusplus.com?

Wrong output when printing a string from inside a struct pointer (VC++ 2010)

I've found a very strange issue with both printf (and printf_s), and also std::cout. I'm not sure if it's some short of "glitch" or error in these functions, or if I'm doing something wrong. Since both functions do the same, I'm assuming I'm not doing it the right way.
I have the following structures in my program (By the way, this is a Visual C++ 2010 project):
#pragma pack(push, 1)
typedef struct nameentry
{
char NAME[17];
char EXT[4];
}NAMEENTRY;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct fileentry
{
unsigned int ID;
NAMEENTRY FILENAME;
unsigned int GPFID;
unsigned long long int FPOINTER;
size_t FILESIZE;
}FILEENTRY;
#pragma pack(pop)
Now I have the following portion of code:
NAMEENTRY fname = MCreateNameEntry("LONGFILE.JPG");
FILEENTRY* myfile_ = SearchFileByPkgID(0, fname);
printf("%s", myfile_->FILENAME.NAME);
So what this code is supposed to do is, create an instance of NAMEENTRY with NAME=LONGFILE, and EXT=JPG. Both character arrays are null terminated (last byte is a 0). Then create an instance of FILEENTRY with it's corresponding data from a database I'm developing, then print the name of the file from the FILEENTRY's NAMEENTRY structure.
After running the code, what I get instead of the name of the file, is... garbage. The classic garbage you get when trying to print text from a bad pointer. If I try to print any of the other fields, I also get wrong values.
So obviously, my first thought was that one of my functions were not returning the right value. So I started inspecting the code and, to my surprise, they are actually returning the right values and the structure is filled with the right data. I get the proper values in each field, every character array ends with a 0, etc.
So then I said... "What if I copy the entire block into another instance of FILEENTRY?", and I tried this:
NAMEENTRY fname = MCreateNameEntry("LONGFILE.JPG");
FILEENTRY* myfile_ = SearchFileByPkgID(0, fname);
FILEENTRY dMem;
memcpy(&dMem, myfile_, sizeof(FILEENTRY));
printf("%s", dMem.FILENAME.NAME);
And guess what? It works perfectly fine. I get the name of the file, no garbage. So I'm assuming, either the problem is inside of printf (I also tried std::cout with the same results), or I am doing something wrong when using these functions.
Well, that helps. Seems like the problem was trying to return a pointer to a local variable, as Igor Tandetnik suggested.
So as a workaround, I'm not sure if this is a proper way of handling this, instead of define a local variable, I'm using calloc to allocate a memory block for a FILEENTRY pointer, then fill it and return it. And yes, it seems to work this way.
This is the actual code of the function:
FILEENTRY* SearchFileByPkgID(int ID, NAMEENTRY fname)
{
FILEENTRY* myFile = (FILEENTRY*)calloc(sizeof(FILEENTRY),1);
std::vector<int> results;
unsigned int* dptable = GetDPTableByPkgId(ID);
bool found = false;
for(int x = 0; x < 1024; x++)
{
if(dptable[x] > 0)
{
fseek(PDBFILE, dptable[x], SEEK_SET);
fread(myFile, sizeof(FILEENTRY), 1, PDBFILE);
if(strcmp(myFile->FILENAME.EXT, fname.EXT) == 0)
if(myFile->FILENAME.NAME[0] == fname.NAME[0])
results.push_back(dptable[x]);
}
}
for(int y = 0; y < results.size(); y++)
{
fseek(PDBFILE, results[y], SEEK_SET);
fread(myFile, sizeof(FILEENTRY), 1, PDBFILE);
if(strcmp(myFile->FILENAME.NAME, fname.NAME) == 0)
{
found = true;
break;
}
}
results.clear();
if(found)
return myFile;
else
return 0L;
}
Any more suggestions are wellcome.

Array as out parameter in c++

I created a function that returns an error code (ErrCode enum) and pass two output parameters. But when I print the result of the function, I don't get the correct values in the array.
// .. some codes here ..
ErrCode err;
short lstCnt;
short lstArr[] = {};
err = getTrimmedList(lstArr, &lstCnt);
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d", i, lstArr[i]);
// .. some codes here ..
The getTrimmedList function is like this:
ErrCode getTrimmedList(short* vList, short* vCnt)
{
short cnt;
ErrCode err = foo.getListCount(FOO_TYPE_1, &cnt);
if (NoError!=err) return err;
short* list = new short [cnt];
short total = 0;
for (short i=0; i<cnt; ++i)
{
FooBar bar = foo.getEntryByIndex(FOO_TYPE_1, i);
if (bar.isDeleted) continue;
list[total] = i;
++total;
}
*vCnt = total;
//vList = (short*)realloc(index, sizeof(short)*total);
vList = (short*)malloc(sizeof(short)*total);
memcpy(vList, list, sizeof(short)*total)
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d", i, lstArr[i]);
return NoError;
}
where:
foo is an object that holds arrays of FooBar objects
foo.getListCount() returns the number of objects with type FOO_TYPE_1
FOO_TYPE_1 is the type of object we want to take/list
foo.getEntryByIndex() returns the ith FooBar object with type FOO_TYPE_1
bar.isDeleted is a flag that tells if bar is considered as 'deleted' or not
What's my error?
Edit:
Sorry, I copied a wrong line. I commented it above and put the correct line.
Edit 2
I don't have control over the returns of foo and bar. All their function returns are ErrCode and the outputs are passed through parameter.
Couple of questions before I can answer your post...
Where is "index" defined in:
vList = (short*)realloc(index, sizeof(short)*total);
Are you leaking the memory associated with:
short* list = new short [cnt];
Is it possible you have accidentally confused your pointers in memory allocation? In any case, here is an example to go from. You have a whole host of problems, but you should be able to use this as a guide to answer this question as it was originally asked.
WORKING EXAMPLE:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int getTrimmedList(short** vList, short* vCnt);
int main ()
{
// .. some codes here ..
int err;
short lstCnt;
short *lstArr = NULL;
err = getTrimmedList(&lstArr, &lstCnt);
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d\n", i, lstArr[i]);
// .. some codes here ..
return 0;
}
int getTrimmedList(short** vList, short* vCnt)
{
short cnt = 5;
short* list = new short [cnt];
short* newList = NULL;
short total = 0;
list[0] = 0;
list[1] = 3;
list[2] = 4;
list[3] = 6;
total = 4;
*vCnt = total;
newList = (short*)realloc(*vList, sizeof(short)*total);
if ( newList ) {
memcpy(newList, list, sizeof(short)*total);
*vList = newList;
} else {
memcpy(*vList, list, sizeof(short)*total);
}
delete list;
return 0;
}
You have serious problems.
For starters, your function has only one output param as you use it: vCnt.
vList you use as just a local variable.
realloc is called with some index that we kow nothing about, not likely good. It must be something got from malloc() or realloc().
The allocated memory in vList is leaked as soon as you exit getTrimmedList.
Where you call the function you pass the local lstArr array as first argument that is not used for anything. Then print the original, unchanged array, to bounds in cnt, while it has 0 size still -- behavior is undefined.
Even if you managed to pass that array by ref, you could not reassign it to a different value -- C-style arrays can't do that.
You better use std::vector that you can actually pass by reference and fill in the called function. eliminating the redundant size and importantly the mess with memory handling.
You should use std::vector instead of raw c-style arrays, and pass-by-reference using "&" instead of "*" here. Right now, you are not properly setting your out parameter (a pointer to an array would look like "short **arr_ptr" not "short *arr_ptr", if you want to be return a new array to your caller -- this API is highly error-prone, however, as you're finding out.)
Your getTrimmedList function, therefore, should have this signature:
ErrCode getTrimmedList(std::vector<short> &lst);
Now you no longer require your "count" parameters, as well -- C++'s standard containers all have ways of querying the size of their contents.
C++11 also lets you be more specific about space requirements for ints, so if you're looking for a 16-bit "short", you probably want int16_t.
ErrCode getTrimmedList(std::vector<int16_t> &lst);
It may also be reasonable to avoid requiring your caller to create the "out" array, since we're using smarter containers here:
std::vector<int16_t> getTrimmedList(); // not a reference in the return here
In this style, we would likely manage errors using exceptions rather than return-codes, however, so other things about your interface would evolve, as well, most likely.

What could be wrong with this?

BTW: I found the problem: (See my answer below)
When I build my program at home it works fine, but when I use my universities system is crashing on me. When I go at it with GDB I get this:
(gdb) r t.c-
Starting program: /home/shro8822/p5/c- t.c-
*--Code Gen Function: main
*--in function 'main' variable offsets start at 2
Program received signal SIGSEGV, Segmentation fault.
0x08084410 in ObjectCode::ResolveRef (this=0xbfb3dd20) at CodeOutput.cpp:44
44 p->Resolve(this);
(gdb) list
39 {
40 std::list<Patch*>::iterator pos;
41 for(pos = Patchups.begin(); pos != Patchups.end(); ++pos)
42 {
43 Patch* p = *pos;
44 p->Resolve(this);
45 //delete p;
46 }
47
48 }
(gdb) p p
$1 = (class ObjectCode::Patch *) 0x2064696c
(gdb) p this
$2 = (ObjectCode * const) 0xbfb3dd20
It crashes from a SEG-V on a line with a virtual function call involving 2 variable and neither is NULL. I don't think there is anywhere else that stuff from this list is deleted.
Tossing it a Valgrind gives one error:
==5714== Invalid read of size 4
==5714== at 0x8084410: ObjectCode::ResolveRef() (CodeOutput.cpp:44)
==5714== by 0x8086E00: ObjectCode::Finish() (CodeOutput.cpp:196)
==5714== by 0x807EC97: WalkGlobal::Finish() (CodeGen_G.cpp:211)
==5714== by 0x808D53C: Compile::RunV() (cs445.cpp:120)
==5714== by 0x808D7C2: ProcessFile::Run() (cs445.cpp:49)
==5714== by 0x808CCD9: main (cs445.cpp:234)
==5714== Address 0x2064696C is not stack'd, malloc'd or (recently) free'd
Seg fault
Any idea were to start looking?
BTW: I populate the list using only statements like this: Patchups.push_back(new PatchType());
shro8822 p5 $ grep Patchups *.cpp *.h -n
CodeOutput.cpp:41: for(pos = Patchups.begin(); pos != Patchups.end(); ++pos)
CodeOutput_Slot.cpp:124: { Stream->Patchups.push_back(new FunctionPatch(it,GetSlotBefor(),at)); }
CodeOutput_Slot.cpp:126: { Stream->Patchups.push_back(new GotoPatch(target,GetSlotBefor(),at,"goto")); }
CodeOutput_Slot.cpp:128: { Stream->Patchups.push_back(new GotoPatch(target,GetSlotBefor(),at,c)); }
CodeOutput_Slot.cpp:130: { Stream->Patchups.push_back(new BranchPatch(target,GetSlotBefor(),type,from,at,c)); }
CodeOutput.h:222: std::list Patchups;
Yet more: It happens that the home and school systems are both x86 (RHEL 3 and 5 respectively) so I ran the binary I compiled at home on the system at school and it runs fine.
The value of the pointer is probably the victim of a wild write from somewhere else.
The variable p shown in your debugger output is 0x2064696c. That is probably the string "lid ", depending on your byte ordering. You should look for somewhere in your code where that string (or value) was stored.
One of the pointers in your list is invalid. This could be because it is null (not in your case), uninitialized, initialized via a bad cast or the valid object that it once pointed to has been destroyed.
Because it works in one environment and not in another you are probably seeing the results of some undefined behaviour.
When you push the pointers onto the list, what objects are they pointing to and what happens to those objects at the time you call Finish?
You're dereferencing p on line 44 to an object that doesn't exist.
Either p was never initialized, or *p has already been deleted.
Edit: I'd recommend to start looking where this list is populated, and verify that your list items are initialized to 0, and that you actually assign pointers to your Patch instances to the list. Also you might look for other errors or exceptions that you're ignoring or catching during the initialization process that are allowing pointers to invalid memory like this to make it into the list.
How I found the problem.
First a tip of the hat to janm for identifying what was going wrong even if it didn't help much in finding where.
I added a Test function that is effectively a copy of the function that fails, but with all the side effects stripped out. With it running all over the place I was able to isolate where things break down into a small windows. Under the debugger, I single stepped from that last valid pass to the first invalid pass and got this:
CodeOutput.cpp:224 | ObjectCode::Test();
CodeOutput.cpp:225 | continue;
CodeOutput.cpp:111 | while(at != ops.end())
stl_list.h:598 | { return iterator(&this->_M_impl._M_node); }
stl_list.h:127 | : _M_node(__x) { }
stl_list.h:174 | { return _M_node != __x._M_node; }
CodeOutput.cpp:113 | printf("%s\n", (*at).TypeStr());
stl_list.h:132 | { return static_cast(_M_node)->_M_data; }
CodeOutput_asm.cpp:33 | switch(Type)
CodeOutput_asm.cpp:36 | Case(OpPlaceholder);
CodeOutput.cpp:115 | switch((*at).Type)
stl_list.h:132 | { return static_cast(_M_node)->_M_data; }
CodeOutput.cpp:216 | char* c = (*at).comment;
stl_list.h:132 | { return static_cast(_M_node)->_M_data; }
CodeOutput.cpp:217 | if((*at).head != NULL && (*at).head[0] != '\0')
stl_list.h:132 | { return static_cast(_M_node)->_M_data; }
stl_list.h:132 | { return static_cast(_M_node)->_M_data; }
CodeOutput.cpp:222 | ++at;// = ops.erase(at);
stl_list.h:141 | _M_node = _M_node->_M_next;
stl_list.h:142 | return *this;
CodeOutput.cpp:223 | (*at).head = c;
stl_list.h:132 | { return static_cast(_M_node)->_M_data; }
CodeOutput.cpp:224 | ObjectCode::Test();
Formatted for clarity, the memory corruption must be caused by one of these lines:
-- last valid test
CodeOutput.cpp:224 | ObjectCode::Test();
CodeOutput.cpp:225 | continue;
-- falls into loop ('at' is list::iterator)
CodeOutput.cpp:111 | while(at != ops.end())
CodeOutput.cpp:113 | printf("%s\n", (*at).TypeStr());
CodeOutput.cpp:115 | switch((*at).Type)
-- OpPlaceholder case
CodeOutput.cpp:216 | char* c = (*at).comment;
-- if gets false ('head' is char*)
CodeOutput.cpp:217 | if((*at).head != NULL && (*at).head[0] != '\0')
CodeOutput.cpp:222 | ++at;
CodeOutput.cpp:223 | (*at).head = c;
-- first invalid test
CodeOutput.cpp:224 | ObjectCode::Test();
-- called from CodeOutput.cpp:113
CodeOutput_asm.cpp:33 | switch(Type)
CodeOutput_asm.cpp:36 | case OpPlaceholder; return "OpPlaceholder";
Because that not to long a list, I just added even more logging till I found that these line causes the problem:
++at;
(*at).head = c;
Now that I know exactl where to look it easy to see the problem, and by switching to:
++at;
if(at != ops.end()) (*at).head = c;
the problem goes away.
The only questions I still have are 1) why did it work at all on my old system? and 2) why didn't that manifest as a seg-v right on the second line? I would think that having *(list.end()) result in a reference to NULL would be a good thing.
You should use < in your conditional statement.
When you increment a pointer using ++, it increases it by the size of whatever it points to. Since you're using !=, it's possible that you're not hitting Patchups.end() exactly, and so you're walking off then end into invalid memory.
Or it might be something else. There might be invalid memory somewhere between begin() and end(), for example.