Related
I'm trying to figure out how I could make a linked list which links to a single byte array. So each element I put into the byte array could be enqued() and dequeued(). However, I need to figure out how to do this using pointer offsets and linked lists.
My question is:
How do I get an offset of a set amount from the start of a pointer? For example, let's say the beginning of my list is at one pointer. I would start by just checking if that space is empty, if not, get the next value in the list. How do I offset from a current pointer position and get a new pointer location that is basically just an offset of another pointer, forward or backwards, up or down, left and right, plus or minus.
Someone asked for an example:
byte myData[1024];
I have to store all of my data into this. This is for a class assignment. Essentially, I have to use this array to store any and all of my data to it, and basically create a queue, like the standard c++ queue. I have to create Enqueue() and Dequeue() functions and then dynamically allocate the memory for each. I have a general idea of what I'm doing. I'm stuck on trying to figure out how to take a pointer of my current position, and then set it to a new position, and then have that be my "next" in the list.
It sounds like what you really want is pointer arithmetic. It's simple enough.
std::int32_t foo[] = {42, 350};
std::int32_t* intPtr = &foo; // We'll say foo is at address 0x005
++intPtr; // Or intPtr += 1, either way the value of intPtr is now 0x009
// *intPtr would now give you 350.
// Your program knows the type being pointed to, and bumps up the address
// accordingly. In this case a 4-byte integer
When doing pointer arithmetic on a C-array, it's important to have checks in place to stop you going out of bounds on either side. However, I don't even think pointer arithmetic is necessary. If you're storing an array privately, simply using index access and tracking what index your list ends at is a lot simpler. You still have to do checks, but their easier checks.
You're also saying linked list, but describing an array list. They are two very different data structures. Your queue will be a lot easier to write if you write a separate array list class, and store an array list object in your queue instead or a raw array.
How do I get an offset of a set amount from the start of a pointer?
Read the C++11 standard n3337 about pointer arithmetic. Notice the existence of offsetof in C++.
If you have two short*ptr1; and short*ptr2; pointers which contain a valid address, you might code ptr1 - ptr2 or ptr1 + 5 or ptr2 - 3 (however, ptr1+ptr2 is forbidden). The C++11 standard explains when that is valid (sometimes it is not, e.g. when ptr2 is the nullptr). Notice also that in general &ptr1[3] is the same as ptr1+3 and ptr2[-1] is exactly *(ptr2-1) (when that makes sense).
Beware of undefined behavior in your code, such as buffer overflows (and you will have one if you do pointer arithmetic carelessly: beware of segmentation faults).
Tools like address sanitizers, debuggers (such as GDB), valgrind should be helpful to understand the behavior of your code.
Don't forget to enable warnings and debug info in your C++ compiler. Once your C++ code compiles without warnings, read how to debug small programs. With GCC, compile with g++ -Wall -Wextra -g. Notice that GCC 10 adds some static analysis abilities. And you could use the Clang static analyzer or Frama-C (or develop your own GCC plugin).
The linked list wikipage has a nice figure. The wikipage on tries could help you also.
I recommend reading a good C++ programming book and then some introduction to algorithms.
On github or elsewhere you can find tons of examples of C++ code related to your question (whose terminology is confusing to non-native English speakers).
Academic papers about memory shape analysis (such as this one or that one) contain figures which would improve your understanding. Books or web resources about garbage collection are also relevant.
My question is basically when to choose QVector and when to choose QList as your Qt container. What I already know:
Qt docs: QList class
For most purposes, QList is the right class to use. Its index-based API is more convenient than QLinkedList's iterator-based API, and it is usually faster than QVector because of the way it stores its items in memory. It also expands to less code in your executable.
The same is written is this very popular Q&A: QVector vs QList. It also favors QList.
But: on recent Qt World Summit 2015 KDAB presented "Why QList is harmful", this is basically here:
QList considered harmful
Don't use QList, use Q_DECLARE_TYPEINFO
As far as I understand the idea is that QList for almost all types is inefficient when allocating new elements in heap. Each time you are adding new element, it calls new (once per element) and this is inefficient compared to QVector.
This is why now I am trying to understand: is it QVector which we should choose as default container?
Qt advertises QList as the "jack of all trades", but the other half of that saying is "master of none". I'd say QList is a good candidate if you plan on appending to both ends of the list, and those are no larger than than a pointer, as QList reserves space before and after. That's about it, I mean as far as good reasons to use QList are concerned.
QList will automatically store "large" objects as pointer and allocate the objects on the heap, which may be considered a good thing if you are a baby, which doesn't know how to declare a QVector<T*> and use dynamic allocation. This is not necessarily a good thing, and in some cases it will only bloat the memory usage and add extra indirection. IMO it is always a good idea to be explicit about what you want, whether it is pointers or instances. Even if you do want heap allocation, it is always better to allocate it yourself and simply add the pointer to the list than construct the object once, then have have copy construct that on the heap.
Qt will return you a QList in a lot of places where it comes with overhead, for example when getting a QObject's children or you search for children. In this case it doesn't make sense to use a container that allocates space before the first element, as it is a list of objects which are already there, not something you are likely to prepend to. I also don't much like the absence of a resize() method.
Imagine a situation where you have an object with size of 9 bytes and byte alignment on a 64 bit system. It is "far too much" for QList so instead it will use 8 byte pointer + CPU overhead for the slow heap allocation + memory overhead for the heap allocation. It will use twice the memory and with an extra indirection for access it will hardly offer performance advantages as advertised.
As of why QVector cannot suddenly become the "default" container - you don't change horses mid-race - it is a legacy thing, Qt being such an old framework, and even though a lot of stuff has been deprecated, making changes to widely used defaults is not always possible, not without breaking a lot of code, or producing undesired behavior. Good or bad, QList will likely continue being the default all the way throughout Qt 5, and likely in the next major release as well. The same reason Qt will continue using "dumb" pointers, for years after smart pointers have become a must and everybody is crying about how bad plain pointers are and how they should not be used ever.
That being said, nobody is forcing you to use QList in your design. There is no reason why QVector should not be your default container. I myself don't use QList anywhere, and in the Qt functions which return a QList I merely use as a temporary to move stuff into a QVector.
Furthermore, and this is only my personal opinion, but I do find a lot of design decisions in Qt that don't necessary make sense, be that performance or memory use efficiency or ease of use wise, and overall there are a a lot of frameworks and languages which like promoting their ways of doing things, not because it is the best way to do it, but because it is their way to do it.
Last but not least:
For most purposes, QList is the right class to use.
It really boils down to how you understand this. IMO in this context, "the right" does not stand for "the best" or "the optimal", but for "good enough" as in "it will do, even if not the best". Especially if you know nothing about different container classes and how they work.
For most purposes, QList will do.
To sum things up:
QList PROs
you intend to prepend objects no larger than the size of a pointer, since it reserves some space in the front
you intend to insert in the middle of the list objects (substantially) larger than a pointer (and I am being generous here, since you can easily use QVector with explicit pointers to achieve the same and cheaper - no extra copy), since when resizing the list, no objects will be moved, only pointers
QList CONs
doesn't have a resize() method, reserve() is a subtle trap, since it will not increase the valid list size, even if index access works it falls in the UB category, also you will not be able to iterate that list
does an extra copy and heap allocating when object is larger than a pointer, which might also be an issue if object identity matters
uses extra indirection to access objects larger than a pointer
has CPU time and memory usage overheads due to the last two, also less cache friendly
comes with additional overhead when used as a "search" return value, since you are not likely to prepend or even append to that
only makes sense if index access is a must, for optimal prepend and insert performance a linked list might be a better option.
The CON's marginally outweigh the PROs, meaning that while in "casual" use QList might be acceptable, you definitely don't want to use it in situations where CPU time and/or memory usage are a critical factor. All in all, QList is best suited for lazy and careless use, when you don't want to make the consideration of optimal storage container for the use case, which would typically be a QVector<T>, a QVector<T*> or a QLinkedList (and I exclude "STL" containers, since we are talking Qt here, Qt containers are just as portable, sometimes faster, and most certainly easier and cleaner to use, whereas std containers are needlessly verbose).
In Qt 5.7, the documentation was changed concerning the topic discussed here. In QVector it is now stated:
QVector should be your default first choice. QVector<T> will usually give better performance than QList<T>, because QVector<T> always stores its items sequentially in memory, where QList<T> will allocate its items on the heap unless sizeof(T) <= sizeof(void*) and T has been declared to be either a Q_MOVABLE_TYPE or a Q_PRIMITIVE_TYPE using Q_DECLARE_TYPEINFO.
They refer to this article by Marc Mutz.
So the official point of view has changed.
QList is an array of void*.
In its normal operation, it news the elements on the heap and stores a pointer to them in the void* array. Like a linked list, that means that references (but, unlike linked lists, not iterators!) to elements contained in the list remain valid under all container modifications until the element is removed from the container again. Thus the name "list". This datastructure is called an array-list and is used in a lot of programming languages where every object is of reference type (say, Java). It is a very cache-unfriendly data structure, like all node-based containers.
But the resizing of the array-list can be factored into a type-independent helper class (QListData), which is supposed to save some executable code size. In my experiments, it's next to impossible to predict which of QList, QVector or std::vector produces the least executable code.
This would have been a good data type for the many Qt reference-like types such as QString, QByteArray, etc., which consist of nothing more than a pimpl pointer. For these types, QList gained an important optimisation: when the type is not larger than a pointer (and please note that this definition depends on the platform's pointer size - 32 or 64bits), instead of heap-allocating objects, the objects are stored in the void* slots directly.
This is only possible, though, if the type is trivially relocatable. That means it can be relocated in memory using memcpy. Relocation here means I take an object, memcpy it to another address and - crucially - not run the destructor of the old object.
And this is where things started to go wrong. Because unlike in Java, in C++ a reference to an object is its address. And while in the original QList, references were stable until the object was removed from the collection again, by putting them into the void* array this property no longer holds. This is no longer a "list" for all intents and purposes.
Things continued to go wrong, though, because they allowed types that are strictly smaller than a void* to be placed in a QList, too. But the memory management code expects elements of pointer size, so QList adds padding(!). That means that a QList<bool> on 64bit platforms looks like this:
[ | | | | | | | [ | | | | | | | [ ...
[b| padding [b| padding [b...
Instead of fitting 64 bools into a cache line, like QVector does, QList only manages 8.
Things went wrong out of any proportion when the docs started calling QList a good default container. It's not. The original STL states:
Vector is the simplest of the STL container classes, and in many cases the most efficient.
Scott Meyer's Effective STL has several items that start with "Prefer std::vector over...".
What is true in general C++ is not suddenly wrong just because you're using Qt.
Qt 6 will fix that particular design mistake. In the meantime, use QVector or std::vector.
If the size of the QList's element type is greater than the pointer's
size QList performs better than QVector because it doesn't store the
objects sequentially but stores sequentially pointers to heap copies.
I'd tend to say the opposite. It'll be much worse off, when going through the items.
If it stores it as pointers on the heap won't QList be much worse off than QVector? The reason that sequential storage(QVector all the time) is so good is, that is is cache friendly, once you store pointers,you lose the data locality, start getting cache misses and it's horrible for performance.
The "default" container IMHO should be a QVector (or std::vector), if you're worried about lots of reallocation, then preallocate a reasonable amount, pay the once off cost and you'll benefit in the long run.
Use the *Vector by default, if you get performance problems, profile and change as necessary.
Please note that this has completely changed in Qt6:
https://www.qt.io/blog/qlist-changes-in-qt-6
QVector and QList are unified and the model of QVector is used as the underlying implementation. This means that Qt 5 QList's extra level of indirection for generic types is now gone and elements are always directly stored in the allocated memory. QList is the real class, with implementation, while QVector is just an alias to QList. QList in Qt 6 supports optimised prepend. It may now shrink on elements removal without usage of reserve. And the size limit of 2GB is removed.
QList is the best possible container to use generally as the documentation states. If the size of the elements' type is <= of the pointer's size = machine & OS bitness = 4 or 8 bytes then the objects are stored the same way as QVector does - sequentially in memory. If the size of the QList's element type is greater than the pointer's size QList performs better than QVector because it doesn't store the objects sequentially but stores sequentially pointers to heap copies.
In the 32-bit case the picture is as follows:
sizeof( T ) <= sizeof( void* )
=====
QList< T > = [1][1][1][1][1]
or
[2][2][2][2][2]
or
[3][3][3][3][3]
or
[4][4][4][4][4] = new T[];
sizeof( T ) > sizeof( void* )
=====
QList< T > = [4][4][4][4][4] = new T*[]; // 4 = pointer's size
| | ... |
new T new T new T
In case you want your objects to be laid out sequentially in memory no matter the size of their elements, as it is usually the case with OpenGL programming, then you should use QVector.
Here is a detailed description of the QList's internals.
Imagine, that we have DataType class.
QVector - array of objects, such as:
// QVector<DataType> internal structure
DataType* pArray = new DataType[100];
QList - array of pointers to objects, such as:
// QList<DataType> internal structure
DataType** pPointersArray = new DataType*[100];
Therefore, direct access by index will be faster for QVector:
{
// ...
cout << pArray[index]; //fast
cout << *pPointersArray[index]; //slow, need additional operation for dereferencing
// ...
}
But swaping will be faster for QList, if sizeof(DataType) > sizeof(DataType*):
{
// QVector swaping
DataType copy = pArray[index];
pArray[index] = pArray[index + 1];
pArray[index + 1] = copy; // copy object
// QList swaping
DataType* pCopy = pPointersArray [index];
pPointersArray[index] = pPointersArray [index + 1];
pPointersArray[index + 1] = pCopy; // copy pointer
// ...
}
So, if you need direct access without swaping operations between elements (such as sorting, for example), or sizeof(DataType) <= sizeof(DataType*), your better way is use QVector. In other case use QList.
QList behaves differently depending on what's inside (see source code struct MemoryLayout):
if sizeof T == sizeof void* and T is defined Q_MOVABLE_TYPE, then QList<T> behaves exactly like QVector, that is, the data is stored contiguously in memory.
if sizeof T < sizeof void* and T is defined Q_MOVABLE_TYPE, then QList<T> pads each entry to sizeof void*, and loses layout-compatibility with QVector.
in all other cases, QList<T> is a linked list and therefore slow to some degree.
This behavior is what makes QList<T> pretty much always a bad choice, because depending on nifty details, QList<T> is either really a list, or a vector. That's bad API design and prone to errors. (For instance, you will run into bugs if you have a library with a public interface that uses a QList<MyType> internally and in its public interface. sizeof MyType is < sizeof void*, but say you forgot to declare MyType as Q_MOVABLE_TYPE. Later, you want to add Q_MOVABLE_TYPE. This is binary incompatible, meaning that you now have to recompile all code that uses your library, as the memory layout of QList<MyType> changed in the public API. If you are not careful, you will miss this and introduce a bug. This illustrates quite nicely why QList is a bad choice here.)
That said, QList is still not entirely bad: It will probably do what you want most of the cases, but maybe it will do the job behind the scenes differently to what you might expect.
Rule of thumb is:
Instead of QList, use QVector<T> or QVector<T*>, since it explicitly says what you want. You can combine that with std::unique_ptr.
In C++11 and onwards, it is even considered best to just use std::vector, since it will behave correctly in a range-based for loop. (QVector and QList may detach and therefore perform a deep-copy).
You can find all these details and more in a presentation from Marc Mutz and in the video by Olivier Goffart.
I have a question regarding the performance effects when taking into consideration of two possible methods of 'getting' data from a given struct. It is assumed that the 'name' variable is relative to what the value of 'id' is.
Assuming I have a struct and enum as follows,
enum GenericId { NONE, ONE, TWO };
struct GenericTypeDefinition {
GenericId id;
const char name[8];
...
};
Let's say I wanted to get the name of this struct. Quite easy, I could just refer to the instance of the GenericTypeDefinition struct and refer (or point) to the name member. Simple enough.
Now here is where my performance question becomes relevant. Say I need I create hundreds of these instances, all of which will be locked to a certain number of names and a unique id per. These instances will be referred to as a collection of possible 'GenericTypeDefinition's throughout the program. Keep in mind, the value of 'name' is relative to the value of 'id'. My question is, would I be able to save some memory if I implemented a function like follows (and removed the name variable from the struct),
struct GenericTypeDefinition { // 'name' is now removed.
GenericId id;
...
};
const char* Definition_ToString(GenericEnum e) {
switch (e) {
case NONE: return "Nothing";
case ZERO: return "Zero is not nothing.";
...
}
I assume it would because I am freeing up the need to store the string (8 bytes in length) in each struct that I create.
If you would like any clarification please ask, as I have not been able to find much on this.
If I understand what you're asking, you are putting redundant data into your struct. Essentially, you are able to get the name of the struct from the id in the struct. But, you could also store the name directly in the struct.
So, you are right -- not storing the name will save memory, because you won't store the name with every item. The cost is a bit of time. You will need to call a function to give you the name from the id each time you need it. You will have to weigh these tradeoffs to determine which is more important.
The devil is in details. The answer depends on many things. For example, how often such a structure is allocated, how often it is used and how often char name[8]; is used.
If you remove name from the structure, several scenario may happen:
if you have many objects of this type and a good allocator, you will save space.
if you use those objects extensively during some calculus and you use name only from time to time, you will save time thanks to better cache performance.
if you use name extensively for some computation and your function Definition_ToString is just a little bit more complex than the one in your example, you will loose on performance.
However, in my estimation, optimizations like this can speed up program by some small factor only. It may help in cases when you count in microseconds. If your program is desperately slow, look for asymptotically better algorithm.
In most cases compiler will do this job for you. It usually stores all the const string literals in the RO section of the executable.Depending on the optimization level it may even do away with the memory taken up by the char array in the struct. So your executable size will grow,but it won't effect the run time memory.
However since the name is tied to the ID,logically it makes sense to implement the second version,so in future if you want to add a new id,you don't need to do any redundant work.
In your first case, the task of initializing the structs with the proper ID and NAME means that the program will, at the very beginning, copy the literals, this is, the strings (because I assume you initialize the structs with the strings within the code) to another space in RAM memory, to which the char[ ] will point.
Instead, the second case means that the value is read from the program itself (the literals are hard coded in a table somewhere in the deep assembler code), and will return a pointer to it (correct me if the pointer is not to somewhere in the program but the returning const char* is stored as a variable), therefore you do save some memory.
My personal comment is (which you may see it beyond the question's scope), that even though the second alternative may save you some memory, implies that the IDs and NAMEs are hard coded, therefore leaving out any possibility of expansion during runtime (i.e. you want to add more IDs that are received via a console...).
I have a situation where I need to process large (many GB's) amounts of data as such:
build a large string by appending many smaller (C char*) strings
trim the string
convert the string into a C++ const std::string for processing (read only)
repeat
The data in each iteration are independent.
My question is, I'd like to minimise (if possible eliminate) heap allocated memory usage, as it at the moment is my largest performance problem.
Is there a way to convert a C string (char*) into a stl C++ string (std::string) without requiring std::string to internally alloc/copy the data?
Alternatively, could I use stringstreams or something similar to re-use a large buffer?
Edit: Thanks for the answers, for clarity, I think a revised question would be:
How can I build (via multiple appends) a stl C++ string efficiently. And if performing this action in a loop, where each loop is totally independant, how can I re-use thisallocated space.
You can't actually form a std::string without copying the data. A stringstream would probably reuse the memory from pass to pass (though I think the standard is silent on whether it actually has to), but it still wouldn't avoid the copying.
A common approach to this sort of problem is to write the code which processes the data in step 3 to use a begin/end iterator pair; then it can easily process either a std::string, a vector of chars, a pair of raw pointers, etc. Unlike passing it a container type like std::string, it would no longer know or care how the memory was allocated, since it would still belong to the caller. Carrying this idea to its logical conclusion is boost::range, which adds all the overloaded constructors to still let the caller just pass a string/vector/list/any sort of container with .begin() and .end(), or separate iterators.
Having written your processing code to work on an arbitrary iterator range, you could then even write a custom iterator (not as hard as it sounds, basically just an object with some standard typedefs, and operator ++/*/=/==/!= overloaded to get a forward-only iterator) that takes care of advancing to the next fragment each time it hit the end of the one it's working on, skipping over whitespace (I assume that's what you meant by trim). That you never had to assemble the whole string contiguously at all. Whether or not this would be a win depends on how many fragments/how large of fragments you have. This is essentially what the SGI rope mentioned by Martin York is: a string where append forms a linked list of fragments instead of a contiguous buffer, which is thus suitable for much longer values.
UPDATE (since I still see occasional upvotes on this answer):
C++17 introduces another choice: std::string_view, which replaced std::string in many function signatures, is a non-owning reference to a character data. It is implicitly convertible from std::string, but can also be explicitly constructed from contiguous data owned somewhere else, avoiding the unnecessary copying std::string imposes.
Is it at all possible to use a C++ string in step 1? If you use string::reserve(size_t), you can allocate a large enough buffer to prevent multiple heap allocations while appending the smaller strings, and then you can just use that same C++ string throughout all of the remaining steps.
See this link for more information on the reserve function.
To help with really big strings SGI has the class Rope in its STL.
Non standard but may be usefull.
http://www.sgi.com/tech/stl/Rope.html
Apparently rope is in the next version of the standard :-)
Note the developer joke. A rope is a big string. (Ha Ha) :-)
This is a lateral thinking answer, not directly addressing the question but "thinking" around it. Might be useful, might not...
Readonly processing of std::string doesn't really require a very complex subset of std::string's features. Is there a possibility that you could do search/replace on the code that performs all the processing on std::strings so it takes some other type instead? Start with a blank class:
class lightweight_string { };
Then replace all std::string references with lightweight_string. Perform a compilation to find out exactly what operations are needed on lightweight_string for it to act as a drop-in replacement. Then you can make your implementation work however you want.
Is each iteration independent enough that you can use the same std::string for each iteration? One would hope that your std::string implementation is smart enough to re-use memory if you assign a const char * to it when it was previously used for something else.
Assigning a char * into a std::string must always at least copy the data. Memory management is one of the main reasons to use std::string, so you won't be a able to override it.
In this case, might it be better to process the char* directly, instead of assigning it to a std::string.
Update 2:
Well I’ve refactored the work-around that I have into a separate function. This way, while it’s still not ideal (especially since I have to free outside the function the memory that is allocated inside the function), it does afford the ability to use it a little more generally. I’m still hoping for a more optimal and elegant solution…
Update:
Okay, so the reason for the problem has been established, but I’m still at a loss for a solution.
I am trying to figure out an (easy/effective) way to modify a few bytes of an array in a struct. My current work-around of dynamically allocating a buffer of equal size, copying the array, making the changes to the buffer, using the buffer in place of the array, then releasing the buffer seems excessive and less-than optimal. If I have to do it this way, I may as well just put two arrays in the struct and initialize them both to the same data, making the changes in the second. My goal is to reduce both the memory footprint (store just the differences between the original and modified arrays), and the amount of manual work (automatically patch the array).
Original post:
I wrote a program last night that worked just fine but when I refactored it today to make it more extensible, I ended up with a problem.
The original version had a hard-coded array of bytes. After some processing, some bytes were written into the array and then some more processing was done.
To avoid hard-coding the pattern, I put the array in a structure so that I could add some related data and create an array of them. However now, I cannot write to the array in the structure. Here’s a pseudo-code example:
main() {
char pattern[]="\x32\x33\x12\x13\xba\xbb";
PrintData(pattern);
pattern[2]='\x65';
PrintData(pattern);
}
That one works but this one does not:
struct ENTRY {
char* pattern;
int somenum;
};
main() {
ENTRY Entries[] = {
{"\x32\x33\x12\x13\xba\xbb\x9a\xbc", 44}
, {"\x12\x34\x56\x78", 555}
};
PrintData(Entries[0].pattern);
Entries[0].pattern[2]='\x65'; //0xC0000005 exception!!! :(
PrintData(Entries[0].pattern);
}
The second version causes an access violation exception on the assignment. I’m sure it’s because the second version allocates memory differently, but I’m starting to get a headache trying to figure out what’s what or how to get fix this. (I’m currently working around it by dynamically allocating a buffer of the same size as the pattern array, copying the pattern to the new buffer, making the changes to the buffer, using the buffer in the place of the pattern array, and then trying to remember to free the—temporary—buffer.)
(Specifically, the original version cast the pattern array—+offset—to a DWORD* and assigned a DWORD constant to it to overwrite the four target bytes. The new version cannot do that since the length of the source is unknown—may not be four bytes—so it uses memcpy instead. I’ve checked and re-checked and have made sure that the pointers to memcpy are correct, but I still get an access violation. I use memcpy instead of str(n)cpy because I am using plain chars (as an array of bytes), not Unicode chars and ignoring the null-terminator. Using an assignment as above causes the same problem.)
Any ideas?
It is illegal to attempt to modify string literals. Your
Entries[0].pattern[2]='\x65';
line attempts exactly that. In your second example you are not allocating any memory for the strings. Instead, you are making your pointers (in the struct objects) to point directly at string literals. And string literals are not modifiable.
This question gets asked several times every day. Read Why is this string reversal C code causing a segmentation fault? for more details.
The problem boils down to the fact that a char[] is not a char*, even if the char[] acts a lot like a char* in expressions.
Other answers have addressed the reason for the error: you're modifying a string literal which is not allowed.
This question is tagged C++ so the easy way to solve your problem is to use std::string.
struct ENTRY {
std::string pattern;
int somenum;
};
Based on your updates, your real problem is this: You want to know how to initialize the strings in your array of structs in such a way that they're editable. (The problem has nothing to do with what happens after the array of structs is created -- as you show with your example code, editing the strings is easy enough if they're initialized correctly.)
The following code sample shows how to do this:
// Allocate the memory for the strings, on the stack so they'll be editable, and
// initialize them:
char ptn1[] = "\x32\x33\x12\x13\xba\xbb\x9a\xbc";
char ptn2[] = "\x12\x34\x56\x78";
// Now, initialize the structs with their char* pointers pointing at the editable
// strings:
ENTRY Entries[] = {
{ptn1, 44}
, {ptn2, 555}
};
That should work fine. However, note that the memory for the strings is on the stack, and thus will go away if you leave the current scope. That's not a problem if Entries is on the stack too (as it is in this example), of course, since it will go away at the same time.
Some Q/A on this:
Q: Why can't we initialize the strings in the array-of-structs initialization? A: Because the strings themselves are not in the structs, and initializing the array only allocates the memory for the array itself, not for things it points to.
Q: Can we include the strings in the structs, then? A: No; the structs have to have a constant size, and the strings don't have constant size.
Q: This does save memory over having a string literal and then malloc'ing storage and copying the string literal into it, thus resulting in two copies of the string, right? A: Probably not. When you write
char pattern[] = "\x12\x34\x56\x78";
what happens is that that literal value gets embedded in your compiled code (just like a string literal, basically), and then when that line is executed, the memory is allocated on the stack and the value from the code is copied into that memory. So you end up with two copies regardless -- the non-editable version in the source code (which has to be there because it's where the initial value comes from), and the editable version elsewhere in memory. This is really mostly about what's simple in the source code, and a little bit about helping the compiler optimize the instructions it uses to do the copying.