473,396 Members | 1,886 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Wierd Visual Studio Problem

Hi,

I have the following code that I run and compile successfully on Visual Studio 2008 using C, but the problem is when the program tries to run the first free call it just hangs there and does nothing :S. In GNU Linux the program runs fine but windows shows a very strange behavior with this.

here is the code

Create a 2D array dynamically
Expand|Select|Wrap|Line Numbers
  1.  
  2. // now that we have our choice, let's create our dynamic string pointer
  3.         // array using the specified size
  4.         char **sptrTable = (char**)calloc( (tabSize+1), sizeof(int) );
  5.  
  6.         // check for valid allocation
  7.         if( sptrTable == NULL )
  8.         {
  9.             fprintf( stdout,"\nNo memory was allocated due to insufficient memory, please free up some memory and try again\nThe program will now exit\n");
  10.             return ERROR_CODE;
  11.         }
  12.  
  13.         // set our exit code for the allocation size
  14.         sptrTable[tabSize] = (char*)calloc( 1, sizeof(int) );
  15.         sptrTable[tabSize][0] = ALLOCATION_LIMIT;
  16.  
  17.  
Now we later on we will the array:
Expand|Select|Wrap|Line Numbers
  1.  
  2. while ( allocCheck )
  3.         {
  4.  
  5.                         // create the string in the table and
  6.             // check if the memory was allocated ok
  7.             if ( (ptr[index] = (char *)calloc( strlen(buff), sizeof(char) ) ) == NULL )
  8.             {
  9.                 return ERROR_CODE;
  10.             }
  11.  
  12.                         // advance the pointer to next value
  13.                 ptr[index++];
  14.  
  15.                 // check for allocation limit
  16.                 if ( ptr[index] != NULL && ptr[index][0] == (ALLOCATION_LIMIT) )
  17.                 {
  18.  
  19.                                   allocCheck = TRUE;
  20.                                 }
  21. }
  22.  
  23.  
And finally this is the free function used which shows the strange behavious on windows (it stops in the first iteration of the free function):

Expand|Select|Wrap|Line Numbers
  1. void freeChunks( int **ptr, int tabSize )
  2. {
  3.  
  4.     int index = 0;
  5.     int i = 0;
  6.  
  7.         // free the columns
  8.         while( index <= tabSize && ( ptr[index] != NULL) )
  9.         {
  10.             free( ptr[index] );
  11.             index++;
  12.         }
  13.  
  14.         // free the rows
  15.         free( ptr );
  16. }
  17.  
  18.  
The code is corrent and should run fine (it does on Linux using gcc but windows is ><)

Waiting for your responces!
Mar 17 '09 #1
13 2428
Andr3w
42
Hey m8,

Well as it seems maybe linux has a better memory management (and smarter) but it's kinda off the standard to perform such actions. Your code is correct and absolutely right but with one exception, the size needed for allocation of the string.

Picture this:

Expand|Select|Wrap|Line Numbers
  1.  
  2. char *str = "aaaa";
  3.  
  4. printf("%d", strlen(str));
  5.  
  6.  
The code above would return 4 which is correct by all means but as we know strings in C have the following byte syntax (in reality)

1st B -> "a"
2nd B -> "a"
3rd B -> "a"
4th B -> "a"
5th B -> "\0" (a.k.a. NULL termination string)

To free a string the free MUST find a null terminated string in order to de-allocate the memory successfully. Maybe linux libraries are a bit more lenient on this restriction but it must be done (as per C standard).

So the only correction you have to do mate to your code is the following:

Expand|Select|Wrap|Line Numbers
  1.  
  2.  if ( (ptr[index] = (char *)calloc( strlen(buff)+1 /* +1 byte for \0 */, sizeof(char) ) ) == NULL )
  3.              {
  4.                  return ERROR_CODE;
  5.              }
  6.  
  7.  
Cheers!
Mar 17 '09 #2
weaknessforcats
9,208 Expert Mod 8TB
Actually, you are creating a one-dimensional array of char*.

All arrays in C/C++ are one dimensional.

Read this: http://bytes.com/topic/c/insights/77...rrays-revealed.

Pay attention ot the last example.
Mar 18 '09 #3
Andr3w
42
Technically speaking yea I agree, but in this case he created a one-dimensional array of string pointers that point to the actual string. That's why he also had a problem during free because it didn't find where to end deallocation and caused the function to lock ;)
Mar 19 '09 #4
weaknessforcats
9,208 Expert Mod 8TB
That's why he also had a problem during free because it didn't find where to end deallocation and caused the function to lock ;)
What do you mean? The size of an allocated piece of memory is prepended to the address returned by the allocator. You just free the pointer without ever saying how big the allocation is.

If you have a one-dimensional array of char* pointers that point to alocated strings you just loop throught the array and free each pointer and then free the array of pointers.
Mar 19 '09 #5
donbock
2,426 Expert 2GB
@inhaler
In sptrTable you store a pointer to a buffer of size (tabSize+1)*sizeof(int) bytes. That is, a buffer sized to hold an array of tabSize+1 int's, but you declare sptrTable as an array of char-pointers. This only works if int and char* happen to be the same size. You should use sizeof(char*) rather than sizeof(int).

Later, you store a pointer to a buffer of size 1*sizeof(int) in the last sptrTable slot. There's not enough information to tell if sizeof(int) is the correct type in this case. If you truly intend for each sptrTable slot to point at a single int then you should have declared sptrTable as an int** rather than a char**. If so, then you need to use sizeof(int*) in the first calloc.
Mar 19 '09 #6
donbock
2,426 Expert 2GB
@inhaler
"It stops" -- do you mean your program ends, error messages are displayed, and you have a command prompt; or do you mean that your computer hangs and has to be rebooted? Please provide any error messages.
Mar 19 '09 #7
Andr3w
42
Hey guys,

First of all the weakness of cats, if you run the code in a example and try to free it the way the code is posted the program just hangs, while being responsive (i mean the console cursor is flashing) no crashes occur and no exception either. If you are in debugger more in VS you have to either press Cntl + F5 to exit the program or press X to close it while in release build you have to press X to exit it.

If you run the program using GCC and Linux it doesn't stop and continues execution as planned becuase it's a bit more lenient.

Now to donbock, I think you are wrong there the size of a pointer in a 32-bit operating system is 32 bits regardless of the size of the pointed value, and that's why it works.

Now I've compiled an example that demonstrates this, I've tested it in Windows Vista 64 bit using VS2k8 and in Debian Linux using GCC and Vim

I compiled it as a CPP file but I think it's C syntax valid also so...and I tried to use as much as I could the same variables as the initial provided code
Expand|Select|Wrap|Line Numbers
  1. //////////////////////////////////////////////////////////////////////////
  2. //                                                                        //
  3. // Parent Project Name: sample project for bytes
  4. //                                                                        //
  5. // Project file: boom.cpp                            //
  6. //                                                                         //
  7. // Description: Demonstrate offset needed in allocaton                    //
  8. //                                                                        //
  9. //                                                                        //
  10. // Notes:    -                                                            //                                                            
  11. //                                                                        //    
  12. // Date Edited: 2009/03/20                                                //
  13. // Version:    1.0r                                                        //
  14. //                                                                        //
  15. // Coder: Andrew Grammenos (andreas.grammenos@gmail.com)                //
  16. //                                                                        //
  17. // License:    BSD License                                                    //                                    
  18. //                                                                        //
  19. //////////////////////////////////////////////////////////////////////////
  20.  
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <malloc.h>
  24.  
  25. // set the codes
  26. #define        ERROR_CODE 1
  27. #define        ALLOCATION_LIMIT -1
  28.  
  29. // disable this in nix and legacy versions of VS
  30. #pragma warning ( disable : 4996 )
  31.  
  32. // set true false macros
  33. #define TRUE 0;
  34. #define FALSE 1;
  35.  
  36. // forward function declarations
  37.  
  38. int createTable();
  39.  
  40. void freeChunks( char **ptr, int tabSize );
  41.  
  42. int addStringsToTable(char **ptr);
  43.  
  44. int main(int argc, char* argv[])
  45. {
  46.     createTable();
  47.  
  48.     return TRUE;
  49. }
  50.  
  51.  
  52. int createTable()
  53. {
  54.     // example size
  55.     int tabSize = 5;
  56.  
  57.     // now that we have our choice, let's create our dynamic string pointer
  58.     // array using the specified size
  59.     char **sptrTable = (char**)calloc( (tabSize+1), sizeof(int) );
  60.  
  61.     // check for valid allocation
  62.     if( sptrTable == NULL )
  63.     {
  64.         fprintf( stdout,"\nNo memory was allocated due to insufficient memory, please free up some memory and try again\nThe program will now exit\n");
  65.         return ERROR_CODE;
  66.     }
  67.  
  68.     // set our exit code for the allocation size
  69.     sptrTable[tabSize] = (char*)calloc( 1, sizeof(int) );
  70.     sptrTable[tabSize][0] = ALLOCATION_LIMIT;
  71.  
  72.  
  73.     // pass the address of the pointer table to our function
  74.     // that adds the strings
  75.     addStringsToTable( sptrTable );
  76.  
  77.  
  78.     // free up what we used
  79.     freeChunks(sptrTable, tabSize);
  80.  
  81.     return TRUE;
  82.  
  83. }
  84.  
  85. void freeChunks( char **ptr, int tabSize )
  86. {
  87.  
  88.     int index = 0;
  89.  
  90.     // free the columns
  91.     while( index <= tabSize && (ptr[index] != NULL) )
  92.     {
  93.         free( ptr[index] );
  94.         index++;
  95.     }
  96.  
  97.     // free the rows
  98.     free( ptr );
  99. }
  100.  
  101. int addStringsToTable(char **ptr)
  102. {
  103.  
  104.     // create  a buffer to store the string that the user will input
  105.     char buff[BUFSIZ];
  106.     char inB = 0;
  107.  
  108.     int allocCheck = FALSE;
  109.  
  110.     int index = 0;
  111.  
  112.     while ( allocCheck )
  113.     {
  114.         // prompt the user for input
  115.         fprintf(stdout, "\nPlease enter a string (max length is: %d)", BUFSIZ);
  116.  
  117.         // get the input
  118.         fscanf( stdin, "%s", &(buff) );
  119.  
  120.         // create the string in the table and
  121.         // check if the memory was allocated ok
  122.         if ( (ptr[index] = (char *)calloc( strlen(buff) /* + 1 uncomment to run fine ;) */, sizeof(char) ) ) == NULL )
  123.         {
  124.             return ERROR_CODE;
  125.         }
  126.  
  127.         // copy the actual string
  128.         strcpy( ptr[index], buff );
  129.  
  130.         // print diagnostic message
  131.         fprintf(stdout, "\nString successfully inserted\nPlease type any key to continue or E to terminate and press enter\n\n");
  132.  
  133.         // advance the pointer to next value
  134.         ptr[index++];
  135.  
  136.         // check for allocation limit
  137.         if ( ptr[index] != NULL && ptr[index][0] == (ALLOCATION_LIMIT) )
  138.         {
  139.             fprintf(stdout, "\n\nLimit reached exiting now");
  140.             allocCheck = TRUE;
  141.         }
  142.     }
  143.  
  144.  
  145.     return TRUE;
  146.  
  147. }
  148.  
  149.  
  150.  
Mar 19 '09 #8
donbock
2,426 Expert 2GB
@Andr3w
Your program depends on sizeof(int) being the same as sizeof(void*). That is certainly true in some environments; but it is just as certainly false in others. The fact that your program works for one compilers and fails for another suggests a portability problem. I advise you to get in the habit of writing portable code whenever possible.

Hey! What's that pragma on line 30? It looks like you're suppressing a warning. Unsuppress it so we can see if it is a clue to your problems. For that matter, turn on all of the compile-time warnings you can. I trust you will tell us if there are any warnings.
Mar 19 '09 #9
donbock
2,426 Expert 2GB
@Andr3w
It is virtually universal practice to use a nonzero value for true (typically "1") and "0" for false. Was this a typo or did you intend to do it this way? Statements like if(TRUE){...} or while(FALSE){...} will do the exact opposite of what you expect. The hangs you're experiencing might be caused by inadvertently infinite loops.
Mar 19 '09 #10
Andr3w
42
Well, in unix systems true is supposed to be 0 (if a thread is successful it returns 0) and most main function do so. Also most ANSI C functions return 0 when they succeed and a non-zero value if they don't or want to indicate a status (like strlen) Please try to compile the program and see what I am saying by uncommenting the +1 offset that I have in line 122.

Now for the pragma in newer versions of visual studio microsoft has new more "secure" function to replace the legacy printf, fprintf and so on using printf_s, fprintf_s etc, if you don't disable that is nugs you with a warning during compile time in newer versions which is annoying and I tend to disable it all the time :P

We chat so much while the original user hasn't responded yet!! kewl!! ^_* haha
Mar 19 '09 #11
donbock
2,426 Expert 2GB
@Andr3w
I would be happier if you used the terms SUCCESS and FAILURE rather than TRUE and FALSE. The C Standard is clear and unambiguous: an integer value of zero means false and any nonzero value means true.
Mar 20 '09 #12
Andr3w
42
Well, in any case whatever differences we have in our coding style in this post we are not here to debate on how we write code :P at least I think that...
Mar 20 '09 #13
donbock
2,426 Expert 2GB
I would like to continue this discussion of the advantages and disadvantages associated with the values you decide to use for TRUE and FALSE; but I realized that we're hijacking this thread. I copied the relevant posts to the new TRUE/FALSE values: Point / Counterpoint thread where we can continue if you like.
Mar 20 '09 #14

Sign in to post your reply or Sign up for a free account.

Similar topics

26
by: Bruno Jouhier [MVP] | last post by:
I'm currently experiencing a strange phenomenon: At my Office, Visual Studio takes a very long time to compile our solution (more than 1 minute for the first project). At home, Visual Studio...
1
by: paul reed | last post by:
Hello, I am having some weird behavior between two machines...one which is running the 1.1 framework and one which is running 1.0. After opening a child form from a parent...I update the...
18
by: surfrat_ | last post by:
Hi, I am having the following problems in getting Microsoft Visual Studio 2005 Professional to link to an Access .mdb database. Please help me to sort this out. Problem 1: The Microsoft...
8
by: John Nagle | last post by:
Here's a wierd problem: I have a little test case for M2Crypto, which just opens up SSL connections to web servers and reads their certificates. This works fine. But if I execute ...
2
by: Mike Smith | last post by:
We are having an issue where .NET assemblies are inconsistently being found/not found. On some runs, everything runs fine. On other runs, we get exceptions saying that one of our assemblies was...
3
by: Edwin Smith | last post by:
I have a 2 form project in VS2005 that now hangs whenever I try to do anything with the second form. This seems to have started when I added some SQL tables from a Pervasive v.9 database using the...
6
by: Ken Varn | last post by:
When I am running my ASP.NET 2.0 application using VS.NET 2005 ASP.NET Development Server, the session state seems to be getting lost at various times without warning. I am not sure why this is...
0
jwwicks
by: jwwicks | last post by:
Introduction This tutorial describes how to use Visual Studio to create a new C++ program, compile/run a program, resume work on an existing program and debug a program. It is aimed at the...
3
by: Johnson | last post by:
I'm not sure if this is an IIS 5.1 issue or ASP.NET issue, or Visual Studio 2008 issue -- thus posting to 3 groups. Please don't be offended. The problem I'm encountering is that Visual Studio...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.