Because when you do var x: cstring = "1234" you get a pointer to static maybe read-only memory. string has a different problem; you're overwriting its header, not only the character data.
Don't use low level primitives if you don't understand low level details. What is it you're trying to accomplish?
I test memfiles lib, i want to write string to sharememory in one process,and read out from another process
#server side
import memfiles
mm = memfiles.open("test.mmap", mode = fmWrite, newFileSize = 1024) # Create a new file
var str:cstring = "hello,world!"
var map = mapMem(mm, fmWrite)
#copyMem(map, castpointer, len(str))
var temp = castcstring
temp = str
unmapMem(mm, map, -1)
mm.close()
#client side
import memfiles
mm = memfiles.open("test.mmap", mode = fmRead)
var map = mapMem(mm, fmRead)
#copyMem(castpointer, castpointer, sizeof(n1))
var str = castcstring
echo str
The purpose of MemFiles is to put objects into and out of a memory mapped file, so by definition, you have to do low level conversions, especially if your object has a string in it.
It is begging for some "helper" functions that can convert all base types contained in an object, to a form that can be stored in the MemFile, and likewise take a chunk of data from the MemFile and morph it into the required user's object.
MyObj <- helper functions -> mapped memory
If the concept suggested here is ridiculous, then the documentation DEFINITELY needs improving, to help those who ".. don't understand low level details .."
The problem is that the following code:
var s1: cstring = "12345678"
var s2: cstring = ""
copyMem(s2, s1, len(s1))
is essentially equivalent to the following C code:
char *s1 = "12345678";
char *s2 = "";
memcpy(s2, s1, strlen(s1));
And blows up for essentially the same reasons. A cstring is basically just a pointer to a character with some additional smart conversion logic to and from a Nim string. If you want to use copyMem() on such a pointer, you have to ensure that it points to a place that (1) has enough memory allocated and (2) that memory is writeable. String constants live in static memory, they're packed together (so writing eight bytes over a zero-length string will corrupt the data following it), multiple instances are shared (so overwriting the empty string will corrupt all empty strings), and they may be in a read-only section of memory (in which case you'll get a segfault rather than corrupted memory). On top of that, the copy operation above will not copy the trailing zero.
If you want to work on mmaped files, use a ptr to an 8-bit type (char, int8, or uint8) or to an unchecked array. If you want to copy that data elsewhere, either have a fixed-length buffer (e.g., array[N, char]) or allocate a string on the heap (newString(n)). You can get the starting address of either type of buffer with addr(buf[0]).
If you want to do more complex serialization to store data in files (mmaped or otherwise), then much depends on the data you want to serialize.
Edit: Note also that this is mostly an ABI/OS issue, not a Nim issue.