Thread: dynamic array struct

  1. #1
    Registered User
    Join Date
    May 2012
    Posts
    9

    dynamic array struct

    Hi,

    I have a problem to ceate an array which works with the rest of my code.
    The OLD version works but now i want to make dynamic.
    If i try it this way, the display on my board shows only two cryptical symbols.

    I hope someone could help me.

    Thank you in advance

    Code:
    XXX.h
    =======================
    typedef struct
    {
        signed  char  Filename[16];
        ...
        ...
    }
    Files;
    
    XXX.c
    =======================
    
    //OLD
    #define 
    NUMBERS 5
    static Files Array[
    NUMBERS];
    //NEW static unsigned int
    numbers
    ;
    static Files *Array; void main() {
    numbers = (result from a loop) Array= (Files*)malloc(numbers*sizeof(Files));
    .... .... strncpy(Array[0].Filename, ...) }
    The formatting gets always defaced!

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by trep View Post
    Hi,

    I have a problem to ceate an array which works with the rest of my code.
    The OLD version works but now i want to make dynamic.
    If i try it this way, the display on my board shows only two cryptical symbols.

    I hope someone could help me.
    Try posting your full new version of the program, along with the input you give it, the output you expect and the actual output you get. Also, it's int main(void) and return an int at the end (usually 0), and don't cast malloc (read this link and this link).

    A slight improvement over your malloc call:
    Code:
    Array = malloc(numbers * sizeof(*Array));
    Using *Array in the sizeof means if you ever change the type of Array, you don't have to change any malloc statements, it's always allocating the right size. sizeof(*Array) is the size of whatever Array points to.

    EDIT: And of course, remember to always free() the memory you allocate.

    The formatting gets always defaced!
    Copy-paste as plain text. The problems you have are due to your IDE/editor using some sort of "rich text" to display your code, and when you copy it into the forum, it breaks.
    Last edited by anduril462; 05-21-2012 at 03:08 PM. Reason: Clarification and added free comment

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    9
    Thank you for your answer. But it's also not working.
    There should be appear something like that (on the display):
    Song1.wav but it shows a letter and/or pixels

    The whole code is to much for a post.
    So here's the main part.

    Code:
    typedef struct
    {
        CPU_INT08S  pcFilename[16];
        CPU_INT32U  *pucFilePtr;
    }
    tWaveFileInfo;

    Code:
    //#define  NUM_WAVE_FILES  6u
    //static tWaveFileInfo  g_psWaveFiles[NUM_WAVE_FILES];
    
    static CPU_INT32U NUM_WAVE_FILES;
    static tWaveFileInfo  *g_psWaveFiles;

    Code:
    static  void  AppTaskRobotAudioPlayback (void  *p_arg)
    {
        OS_ERR  err;
        CPU_TS  ts;
    
    
       (void)&p_arg;
    
    
    /*
    *********************************************************************************************************
    *                           READ THE WAV-TITLES STORED ON THE SDCARD
    *********************************************************************************************************
    */
        FRESULT fresult;
        CPU_INT32U CountFiles = 0;
        
        //The number of files are counted during a loop... This part is not in the code.
        //So i've passed the value manuell
        NUM_WAVE_FILES = 6;
        g_psWaveFiles = malloc(NUM_WAVE_FILES * sizeof(*g_psWaveFiles));
    
        //Mount the file system (SDCard), using logical disk 0.
        fresult=f_mount(0, &g_sFatFs);
        
        // Open the current directory for access.
        fresult = f_opendir(&g_sDirObject, "/");
    
        // Give message if there's no SDcard.
        if(fresult != FR_OK)
        {
            BSP_DisplayClear();
            BSP_DisplayStringDraw("ERROR!", 30u, 0u); 
            BSP_DisplayStringDraw("-- NO SDCARD --", 2u, 1u);
            while(1){}
        }
    
        
        while(1)
        {
    
            // Read an entry from the directory.
            fresult = f_readdir(&g_sDirObject, &g_sFileInfo);
        
            // Check for error and return if there is a problem.
            if(fresult != FR_OK)
            {
                BSP_DisplayClear();
                BSP_DisplayStringDraw("ERROR!", 30u, 0u); 
                BSP_DisplayStringDraw("-- READING --", 7u, 1u);
                while(1){}            
            }
            
            // If the file name is blank, then stop the loop.
            if(!g_sFileInfo.fname[0])
            {
                break;
            }
        
            // Copy the title to g_psWaveFiles[] - name.ext
            if((g_sFileInfo.fattrib & AM_DIR) == 0) //Ignore directories
            {
                strncpy(g_psWaveFiles[CountFiles].pcFilename, g_sFileInfo.fname, 
                                MAX_FILENAME_STRING_LEN);
                
                // Go to the next file 
                CountFiles++;
        
        }//while
        
    }//void  AppTaskRobotAudioPlayback
        
        
        g_ucCurrentWaveIdx = 0;                                     
        strcpy(pcCurrentWaveTitle, g_psWaveFiles[0].pcFilename);    /* Set the pointer to the first wave in the list.       */
        
    /*
    ***********************************************************************************************************
    ***********************************************************************************************************
    */
        
        while (DEF_ON) {
            OSFlagPend(&AppRobotControlFlagGroup,                   /* Pend until the play button is pressed.               */
                       FLAG_PUSH_BUTTON,
                       0u,
                       OS_OPT_PEND_FLAG_SET_ANY + OS_OPT_PEND_FLAG_CONSUME,
                       &ts,
                       &err);
    
                                                                    /* Get the current wave file information.               */
            BSP_WaveOpen(&g_sFileObject, g_psWaveFiles[g_ucCurrentWaveIdx].pcFilename, &g_sWaveHeader);
    
            BSP_WavePlay(&g_sFileObject, &g_sWaveHeader);            /* Play the file.                                       */
        }
    }
    Last edited by trep; 05-21-2012 at 04:00 PM.

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    • Is this a microcontroller/DSP? If so, please describe the hardware, compiler, etc you are using.
    • How long is your code? Are you sure it's really too long?
    • Have you tried to make the smallest possible program that exhibits your problem? That is, can you write a program that does exactly these three things: allocate space for a string, copy text into that string, and display that string correctly? If that doesn't work, post that program. If it does, you will need to post the full program.
    • That looks nothing like the code you originally posted. Is this the actual code that is causing problems. How can you be sure this is where the problem is? What steps did you take to isolate these 95 lines as the problem?
    • Your braces don't seem to match up properly around lines 60-71, or the comments on the close brackets are wildly inaccurate.
    • The code on lines 74-95 don't appear to belong to any function, so I can not accurately tell you what might be wrong there, I can not see variable declarations, how it is called, etc.
    • One possible problem is that you may not have properly allocated space for pcCurrentWaveTitle, but I can't say, since you didn't provide full code. If it is a global variable, you need to get rid of it and use local variables, and pass them around as needed. Global variables are evil. Read this link.
    • I have no idea what this BSP library is, nor do I care to become an expert in it. It is certainly not standard C. I can't tell you whether you are misusing the library. You may be better off asking your questions on a forum dedicated to that library.
    • You appear to have an infinite loop on line 51.
    • You do not have any checks to make sure CountFiles does not equal or exceed NUM_WAVE_FILES. If it does, you have an array overflow, and you get undefined behavior -- anything could happen including garbage on the display.
    • On line 91, are you sure g_ucCurrentWaveIdx is a valid index? Does it equal or exceed NUM_WAVE_FILE? Again, if it does, you have undefined behavior.

  5. #5
    Registered User
    Join Date
    May 2012
    Posts
    9
    wow... A lot of questions.
    But It's now 2:15 am!
    I will answer you tomorrow.

  6. #6
    Registered User
    Join Date
    May 2012
    Posts
    9
    • I'm woking with a lm3s9b92 from TI / Compiler = IAR Embedded Workbench
    • ... is attached
    • Yes, but I can't get it to work.
    • [That looks nothing ...] Sorry for that. I wanted to make it as uncomplicated as possible.
    • [The rest ...] Sorry, too. I'm using to editors. Notepad++ and the one which is integrated in IAR... They use a different formatting and so I have to correct the taps manually. For typing Natepad and for debugging IAR. Because the editor in IAR is ****. ... and accidently I've copied the wrong code...



    So... Let's start from the beginning.

    I've modified the code now and it should be easier to comprehend.
    The files are attached.

    In this "constellation" it works!

    Don't worry about the loop. It will break on the correct point.
    Because there are 6 wav-files on the card and the define of NUM_WAV_FILES is 6, too.

    The relevant lines are:
    app.c (71-75, 223-267, 369)
    bsp_wav.h (103-108)

    app.c
    bsp_wav.h

    ... I'm still trying to get it to work!

  7. #7
    Registered User
    Join Date
    May 2012
    Posts
    9
    Hmmm... I've used an example from the internet, but the realloc always failed.

    Code again:


    Code:
    typedef struct
    {
        CPU_INT08S  pcFilename[16];
        CPU_INT32U  *pucFilePtr;
    }
    tWaveFileInfo;
    Code:
    static CPU_INT32U NUM_WAVE_FILES;
    static tWaveFileInfo  *g_psWaveFiles;
    Code:
     
       
    ...........
    
        CPU_INT32U CountFiles = 0;
        tWaveFileInfo *tmp;  
        g_psWaveFiles = NULL;
        
    ...........
        
        //Open the main directory
        fresult = f_opendir(&g_sDirObject, "/");
        
        if(fresult == FR_OK)
        {
            for(;;)
            {
                //read the directory
                fresult = f_readdir(&g_sDirObject, &g_sFileInfo);
                if(fresult == FR_OK)
                {
                    // If the file name is blank, then stop the loop.
                    if(g_sFileInfo.fname[0] == 0)
                    {
                      break;
                    }             
                    
                    // Copy the title to g_psWaveFiles[] - name.ext
                    // ... and ignore directories
                    if((g_sFileInfo.fattrib & AM_DIR) == 0)
                    {
                        tmp = (tWaveFileInfo*)realloc(g_psWaveFiles (CountFiles+1)*sizeof(tWaveFileInfo));
                        
                        if( tmp == NULL )
                        {
                            BSP_DisplayClear();
                            BSP_DisplayStringDraw("ERROR!", 30u, 0u); 
                            BSP_DisplayStringDraw("-- REALLOC --", 4u, 1u);
                            while(1){}
                        }
                        
                        g_psWaveFiles = tmp;
                        strcpy(g_psWaveFiles[CountFiles].pcFilename, g_sFileInfo.fname);
                        
                        CountFiles++;
                    }
    
                }//f_readdir
                
            }//for
            
        }//f_opendir
        
        NUM_WAVE_FILES=CountFiles;
    
    ............

  8. #8
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Sorry, been busy at work. Nothing obvious stands out to me at first glance. I do see some possible buffer overflows and unterminated strings, which could be a problem. strcpy doesn't check for length, so you must be absolutely sure that you have enough space in the destination string to contain all the chars in the source string plus one for the null terminator. Where you used strncpy in the code you attached, be aware that strncpy does not null terminate the destination if the source is too long.

    Your usage of realloc looks correct with the exception of a missing comma after g_psWaveFiles. Can you tell if the realloc works at least once, then fails, or does it never work? Maybe modify the program to print the value of CountFiles when realloc failed.

    I'm not familiar with your hardware or this BSP (if it's Micrium, they wont let me download documentation). It is entirely possible that you don't have support for malloc/realloc functions. This is common enough in tiny embedded systems, so if malloc and realloc always fail, even for a very small number of bytes, this may be the case. You would have to read the documentation for your hardware and software.

  9. #9
    Registered User
    Join Date
    May 2012
    Posts
    9
    Thank you very much for your efforts

    I do see some possible buffer overflows and unterminated strings, which could be a problem. strcpy doesn't check for length, so you must be absolutely sure that you have enough space in the destination string to contain all the chars in the source string plus one for the null terminator. Where you used strncpy in the code you attached, be aware that strncpy does not null terminate the destination if the source is too long.
    I think that's not the problem, because it works with the "old" version.

    But after reading this:

    It is entirely possible that you don't have support for malloc/realloc functions. This is common enough in tiny embedded systems, so if malloc and realloc always fail, even for a very small number of bytes, this may be the case. You would have to read the documentation for your hardware and software.
    I've found out, that you can set the stack size in each task.
    This will maybe solve the problem. I'll give it a try!

    Code:
        OSTaskCreate((OS_TCB     *)&AppTaskRobotAudioPlaybackTCB,               
                     (CPU_CHAR   *)"Audio Playback Task",
                     (OS_TASK_PTR ) AppTaskRobotAudioPlayback,
                     (void       *) 0,
                     (OS_PRIO     ) APP_TASK_ROBOT_AUDIO_PLAYBACK_PRIO,
                     (CPU_STK    *)&AppTaskRobotAudioPlaybackStk[0], 
                     (CPU_STK_SIZE) APP_TASK_ROBOT_AUDIO_PLAYBACK_STK_SIZE / 10u,
                     (CPU_STK_SIZE) APP_TASK_ROBOT_AUDIO_PLAYBACK_STK_SIZE,
                     (OS_MSG_QTY  ) 0u,
                     (OS_TICK     ) 0u,
                     (void       *) 0,
                     (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                     (OS_ERR     *)&err);
    BSP are example Code/Function in c. Most of them are from Texas Instuments and they (Micrium) called it after small modifications "BSP".

    And yes, you are right. If you don't have a valid email address from a company, you can't download stuff from their website.

    missing comma

    That happens by editing the text!

  10. #10
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by trep View Post
    I've found out, that you can set the stack size in each task.
    This will maybe solve the problem. I'll give it a try!
    This will probably not fix your problem. The stack is where function parameters and automatic local variables are stored ("automatic" is the opposite of "static", i.e. variables that disappear when the function exits). The malloc/realloc functions allocate memory from a different region called the heap, which allows the memory to be available after the function that malloc's it exits. You would be better off looking for settings related to the heap.

  11. #11
    Registered User
    Join Date
    May 2012
    Posts
    9
    I've got a simple solution on a different way!
    It's not the best, but it should do the job, for what it will be used.

    The array can be filled with a defined size of elements. (e.g. 50)
    NUM_WAVE_FILES = CountedFiles (e.g. 10)
    So the programm knows the amount of files which can be played, without buffer overflows.

    I hope it's understandable!



    I've also checked a few things about Micrium µC-OS


    • Malloc is supported. But I've no idea why it won't work.
    • It's possible to expand the heap size. However the effort only for testing, it's not worth it.
    • There are some functions for memory allocating. But only for defined sizes.


    Therefor I can live with the current version.

    Thank you once again!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Please help with struct and dynamic array problem
    By stephenb in forum C Programming
    Replies: 5
    Last Post: 10-19-2011, 06:02 AM
  2. dynamic array of struct within dynamic array of struct
    By explodecomputer in forum C Programming
    Replies: 3
    Last Post: 08-03-2010, 03:25 AM
  3. dynamic array in STRUCT
    By cfdprogrammer in forum C Programming
    Replies: 15
    Last Post: 08-04-2009, 09:57 AM
  4. Dynamic memory alloction for my array of struct
    By pears0 in forum C Programming
    Replies: 13
    Last Post: 03-11-2005, 11:53 AM
  5. Replies: 4
    Last Post: 03-18-2003, 06:30 PM