views:

66

answers:

3

As suggested: I have a file which is larger than 2 giga. I am mapping to memory using the following function:

char* ptr = (char*) MapViewOfFile( map_handle, 
      FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 );

I parse ptr to rapidxml which accepts Ch* . As per the documentation from rapidxml ptr should be modifiable but since it is declared to be of type char* this cannot be done. Program compiles but when during runtime it crashes with the following error: Access violation. I found out that this occurs when I am parsing the char*. How do I get round this please?

+2  A: 

Blind guess: ptr is probably NULL. From the documentation

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

If you give more information we probably can help more. Check the return value in the debugger. Regarding the first handle parameter map_handle: CreateFileMapping and OpenFileMapping functions return this handle. Maybe you used some other function to get a handle?

jdehaan
Sorry, the language is C++. map_handle is created using CreateFileMapping. ptr is not NULL. When I std::cout ptr I get the actual contents of the file. GetLastError returns 0 (fine). However, in the debugger the program crashes in rapidxml header i.e. return BAD_PTR where it is attempting to modify the actual xml file (to terminate the file). I tried to create a string literal char* xml = "<?xml version=\"1.0\" encoding=\"latin-1\"?> <request> </request>"; and the parse this to parse<0>(xml) and the still I get Access Violation. If I pass declare xml as array it works though.
+1  A: 

Your "Access Violation" is a memory access error. In other words, your program accessed memory it didn't own. This is probably caused by your parser trying to read beyond the bounds of the memory allocated to the file, or, like jdehaan suggests, your MapViewOfFile function is returning NULL.

UPDATE:

If MapViewOfFile is not returning NULL, then the problem is probably that you are accessing beyond the allocated range for the mapped file. You seemed to indicate in your comments on this question that the parsing operation is also modifying the xml document by adding some terminating tags. This will undoubtedly increase the length of the file and, thus, write past the end of the file's block in memory. That would cause the error you are seeing.

If it isn't that, then perhaps you didn't call CreateFileMapping with the proper access specifiers. The documentation for MapViewOfFile says that you need to specify the PAGE_EXECUTE_READWRITE option when you create the file mapping object if you want a map view which allows read/write access.

If it isn't that, then I would suspect that Hans' answer could be the key. What system are you running this on? Is it 32-bit Windows, or 64-bit? If the file is larger than 2GB, you won't be able to map it.

A. Levy
Good point about reading past the end of the file. The mapping is not guaranteed to have a null terminator unless the file itself contains one.
bk1e
You mean that if I declare something like this char* xml = "<xml>"; xml will not be null terminated explaining the crash
No, a string literal is always null terminated. The compiler will ensure that. bk1e was saying that the data you get from MapViewOfFile might not have a null terminator. Even if it does, if your parsing code ignores it then you will still get the same problem. I didn't know the details of your parsing code, so I just guessed that it was possible that it over-ran the memory boundaries. Buffer over-run errors are very common, so that is usually a top candidate to check.
A. Levy
Yet this does not explain why if I initialize char* xml = "<xml>..." and parse this to the xml I get access violation. But if I use an array instead i.e. char xml[] = "<xml>..." this does not crash as was pointed out above.
Ah...does your parser attempt to modify the data that it is parsing? If so, I think I might know why you are seeing the access violation. Your compiler/linker will arrange for the string literals to be loaded into a page of memory that is marked as read-only. So attempts to modify it will result in an exception. In the second example, the string literal is copied into a mutable array of chars that resides on the stack, so you are allowed to modify it. See this question: http://stackoverflow.com/questions/3012113/read-only-memory-and-heap-memory
A. Levy
Ok you are right from the debugger info. but then I have created MapViewOfFile as a char*. Do you mean I can't use this because it returns a constant char * which cannot be modified. Still how can I use MapViewOfFile and still use rapidxml parser?
You specified that the mapped view should be READ and WRITE in your function call, so you will get a pointer to memory which you can both read and write. I'll update my answer with some more theories...
A. Levy
64 bit machine is being used.FILE_MAP_ALL_ACCESS is being parsed to MapViewOfFile. But the problem is that I am casting it as char*. Like you rightly stated rapidxml is trying to add terminators to this xml file. When it does this it crashes in my debugger with BAD_PTR. This does not happen with arrays. In fact, it does not even go to the place where it would have to add a terminator which is the case with char*. If I do the same operation on unix using memory allocation and parsing a char* it works. The same operation done on windows 64 bit with MapViewOfFile failed when I parsed the char*.
+3  A: 

You are passing a 0 for the last argument of MapViewOfFile(). That argument is named dwNumberOfBytesToMap. Since you picked zero, the entire 2 gigabytes is going to be mapped. This cannot work in 32-bit mode, there is not nearly enough virtual memory available. The ptr value will be NULL, any attempt to write through the pointer is going to generate an AV.

You'll need to map sections of the file.

Hans Passant
MapViewOfFile treats zero as a special value; it maps the entire file mapping (or rather from the specified offset to the end of the file mapping).
Luke
Good point, post updated.
Hans Passant