Thread: Error: assignment of i_value in read-only object

  1. #1
    Registered User
    Join Date
    Jul 2020
    Posts
    47

    Error: assignment of i_value in read-only object

    Hello,

    I have two programs that to the best of my knowledge use the same data structures and contain the same statements.

    One program works and the other fails with the error in the title. No doubt there is a reason, but at this stage it is not clear to me.

    Please refer to the two attachments:
    1. Example_Data_Structure
    2. Linked_List_Example


    Example_Data_Structure is a short program that builds and executes as I would expect.

    Example_Data_Structure contains an extract of code from Linked_List_Example.

    For some reason the code works fine in isolation, but not when combined with the other statements.

    It's a mystery to me.

    Linked_List_Example, contains a lot more code (sorry), but also contains the same code as in Example_Data_Structure. I've had to include the whole program because obviously there is something in it which causes the following statement to fail.

    Code:
    record->i_value = 100;
    For reason;
    Code:
    162|error: assignment of member ‘i_value’ in read-only object|
    For some reason I can't upload the other program. No errors but it doesn't appear in the Attachment Manager.

    Also the Attachment Manager states that uploaded programs are supposedly deleted after 1 hour; but my upload from yesterday is still there?
    Attached Files Attached Files

  2. #2
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    I don't have access to Attachments in 'My Settings' ?

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Example_Data_Structure.c seems fine to me.
    Code:
    $ gcc -Wall Example_Data_Structure.c 
    $ ./a.out 
    Record - detail: some string
    Record - value:  100
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Quote Originally Posted by Salem View Post
    It seems fine to me.
    Yes it is, the issue is that the same code in the other example doesn't work.

    I'm assuming that the issue must be due to some of the other statements I have in the 2nd program; it is not at all clear to me why the error is occurring.

    So I need to upload the other example so that I can get an informed opinion.

    The attachment manager seems buggy to me. It always seems to take multiple attempts to get an attachment to upload / appear; and I've not managed to upload the 2nd program at all??

  5. #5
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Finally managed to upload the 2nd attachment
    Attached Files Attached Files

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well the big problem is you're missing a brace at the end of the else in add_record()
    Error: assignment of i_value in read-only object-missing-brace-png

    Then
    Code:
    foo.c: In function ‘add_key’:
    foo.c:54:22: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
             current->key = key;
                          ^
    foo.c:73:28: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
             current->next->key = key;
                                ^
    Use strcpy to copy things.

    Code:
    foo.c: In function ‘add_record’:
    foo.c:89:9: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
             if (current->record_list = NULL) {
             ^
    foo.c:121:13: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
                 if (current->record_list = NULL) {
                 ^
    You probably meant to use ==


    There's no reason to cast the return result of malloc.
    > record_list = (record_t *) malloc(sizeof(record_t));
    Casting malloc - Cprogramming.com
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Quote Originally Posted by Salem View Post
    There's no reason to cast the return result of malloc.
    > record_list = (record_t *) malloc(sizeof(record_t));
    Casting malloc - Cprogramming.com
    Appreciate your reply, I must admit I have been programming on my laptop and with the smaller screen I was having trouble seeing the whole function. I should have used the "-" minus key to condense the code blocks to make sure that I had all the brackets matched up.

    I'm afraid I don't understand your last comment regarding casting malloc.

    Unfortunately I'm none the wiser, even after reading the included link.

    My understanding is that each time I add a new "record" in the list. I need to allocate memory for that record.

    And the statement
    Code:
    record_list= (record_t*) ...
    is the statement required to allocate the memory for the next record/structure in the list, before then populating the fields in the record.

    Can you show the statement that I should be using instead?

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    I mean you should be able to do this without upsetting the compiler.

    Code:
    record_list = malloc(sizeof(record_t));
    The cast would cover up the mistake of not including stdlib.h

    If you get a message along the lines of 'cannot convert void* to type*', then that means you're using C++ to compile your C program.
    This is something you shouldn't be doing either.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Quote Originally Posted by Salem View Post
    The cast would cover up the mistake of not including stdlib.h

    If you get a message along the lines of 'cannot convert void* to type*', then that means you're using C++ to compile your C program.
    This is something you shouldn't be doing either.
    The includes that are specified are:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    The compile options that I'm using are:
    Code:
    -------------- Build: Debug in Linked_List_example_with_Data_Structure_II (compiler: GNU GCC Compiler)---------------
    gcc -Wall -g  -c /home/dev/c/learn/Linked_List_example_with_Data_Structure_II/main.c -o obj/Debug/main.o
    gcc  -o bin/Debug/Linked_List_example_with_Data_Structure_II obj/Debug/main.o   
    Output file is bin/Debug/Linked_List_example_with_Data_Structure_II with size 10.74 KB
    Process terminated with status 0 (0 minute(s), 0 second(s))
    0 error(s), 0 warning(s) (0 minute(s), 0 second(s))

  10. #10
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    There is still an error in the add_record function.

    Using the debugger I observe that the execution crashes at line 96

    Code:
    strcpy(current->record_list->c_detail1,record->c_detail1);
    Unfortunately this statement looks correct to me.

    I've used printf at line 92 & 93 to confirm that the record details (i.e. the "inputs" are correctly set.

    Perhaps the issue is with line 95,

    Code:
    record_list = (record_t *) malloc(sizeof(record_t));
    although I don't observe any errors when this line is executed

    PS: I had issues uploading the attachment again. Does anybody else have issues with this. I'm using latest version of Chrome on Windows
    Attached Files Attached Files

  11. #11
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    Quote Originally Posted by VeeDub View Post

    Code:
    strcpy(current->record_list->c_detail1,record->c_detail1);
    current->record_list is NULL on line 96, as proven by line 89, and then you're trying to dereference (i.e. you're effectively trying to do NULL->c_detail1) so it crashes.

    On line 95, where is record_list even declared? Same for line 109... does this compile? Edit: nvm, I see now that it's a global that is somewhat hidden because it's indented badly. Why is it global?

  12. #12
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Quote Originally Posted by Hodor View Post
    current->record_list is NULL on line 96, as proven by line 89, and then you're trying to dereference (i.e. you're effectively trying to do NULL->c_detail1) so it crashes.

    On line 95, where is record_list even declared? Same for line 109... does this compile? Edit: nvm, I see now that it's a global that is somewhat hidden because it's indented badly. Why is it global?
    Hello Hodor,

    My understanding is that line 95
    Code:
    record_list = (record_t *) malloc(sizeof(record_t));
    Allocates memory for a new record, which I then update in lines 96, 97 and 98.

    If I comment line 96
    Code:
    strcpy(current->record_list->c_detail1,record->c_detail1);
    Then line 97 fails
    Code:
    current->record_list->i_value = record->i_value;
    So the issue must be in line 95
    Code:
    record_list = (record_t *) malloc(sizeof(record_t));
    But a similar statement works earlier in the code (line 161) to create a record structure
    Code:
    record = (record_t *) malloc(sizeof(record_t));
    and I successfully update this record in main(); so I don't understand why line 95 isn't working.

    As to why the record structure is a global variable. My intention is to access and update the record structure in a number of functions - not just add_record.

  13. #13
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    When your code reaches line 96, what is the value of current->record_list? As far as I can see it's NULL, because program execution only reaches line 96 if current->record_list is NULL (see line 89; i.e. it's still NULL when line 96 is reached). You can't do

    Code:
                strcpy(current->record_list->c_detail1,record->c_detail1);
    Because the part in bold must be NULL otherwise the line would never have been reached because execution only reaches line 96 if the part in bold is NULL (because of line 89).

    Maybe before reaching line 96, and after line 89, you have to do something like

    Code:
    current->record_list = record_list;
    (But don't quote me on that I haven't looked very closely at your code because I'm on a device that makes it difficult for me. That said you have to either add something like the line above or change lines 96-98 to use record_list rather than current->record_list or something else that is not NULL)

    Edit: What I'm suggesting is either :
    Code:
            /* Check head of record list */
            if (current->record_list == NULL) {
                /* First record */
    
    //          printf("Record - detail: %s\n",record->c_detail1);
    //          printf("Record - value:  %d\n",record->i_value);
    
                record_list = (record_t *) malloc(sizeof(record_t));
    current->record_list = record_list;
                strcpy(current->record_list->c_detail1,record->c_detail1);
                current->record_list->i_value = record->i_value;
                current->record_list->next = NULL;
    
            } /* current->record_list == NULL */
    or

    Code:
            /* Check head of record list */
            if (current->record_list == NULL) {
                /* First record */
    
    //          printf("Record - detail: %s\n",record->c_detail1);
    //          printf("Record - value:  %d\n",record->i_value);
    
                record_list = (record_t *) malloc(sizeof(record_t));
                strcpy(record_list->c_detail1,record->c_detail1);
                record_list->i_value = record->i_value;
                record_list->next = NULL;
    
            }
    Last edited by Hodor; 07-18-2020 at 10:14 PM.

  14. #14
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Thanks Hodor,

    You're right of course

    Line 95 should have been
    Code:
    current->record_list = (record_t *) malloc(sizeof(record_t));
    If I keep making enough mistakes I'll eventually start to learn.

    I just need to get to the point where I can fix them by myself.

    Cheers

  15. #15
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    Quote Originally Posted by VeeDub View Post
    Thanks Hodor,

    You're right of course

    Line 95 should have been
    Code:
    current->record_list = (record_t *) malloc(sizeof(record_t));
    If I keep making enough mistakes I'll eventually start to learn.

    I just need to get to the point where I can fix them by myself.

    Cheers

    I made an edit while you were replying. Your way in this new post is fine as well, of course

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to read 2 adjacents strings object
    By piero borrelli in forum C++ Programming
    Replies: 3
    Last Post: 09-03-2014, 11:54 AM
  2. int assignment to object incompatibility issue - Java
    By Delicieuxz in forum General Discussions
    Replies: 9
    Last Post: 11-26-2013, 01:58 AM
  3. Replies: 7
    Last Post: 12-07-2012, 10:44 PM
  4. Operator Overloading - RHS object is modified by assignment operation
    By IdioticCreation in forum C++ Programming
    Replies: 16
    Last Post: 12-30-2010, 07:33 AM
  5. assignment of read-only location (vectors)
    By jlangfo5 in forum C++ Programming
    Replies: 4
    Last Post: 12-17-2010, 09:20 AM

Tags for this Thread