How to properly zero-initialize a generated type (traditional C++)

3 posts / 0 new
Last post
Offline
Last seen: 5 years 9 months ago
Joined: 10/01/2015
Posts: 17
How to properly zero-initialize a generated type (traditional C++)
The problem appears to be sequence's default constructor is marked explicit. What I've tried:
  1. Type t;
    This leaves fields uninitialized, it's what I'm trying to avoid.
  2. Type t{};
    This *should* be the solution, but it does not compile (clang, mac) due to the sequence's explicit default constructor.
  3. Type t; std::memset(&t, 0, sizeof(t));
    This is undefined behavior because std::is_trivialy_copyable::value == false.
  4. Type t; TypeSupport::initialize_data(t);
    This does not zero anything. In fact, if the pointer for the string is a junk value, it will attempt to dereference it resulting in UB.
IDL:
struct NestedType{
	long dummy;
}; //@top-level false

struct Type {
	short id; //@key
	string<256> value;
	sequence more_values;
};
Keywords:
Offline
Last seen: 2 months 2 weeks ago
Joined: 04/02/2013
Posts: 196

Hi,

TypeSupport::initialize_data should initialize the sample. It should set primitive types to zero, allocate memory for the string and the sequence, and make them empty.

If you review the generated code, this is the function that would initialize your 'Type' (I made the sequence a sequence of shorts for simplicity):

RTIBool Type_initialize_w_params(Type* sample, const struct DDS_TypeAllocationParams_t * allocParams)
{

    void* buffer = NULL;
    if (buffer) {} /* To avoid warnings */

    if (allocParams) {} /* To avoid warnings */

    if (!RTICdrType_initShort(&sample->id)) {
        return RTI_FALSE;
    }

    if (allocParams->allocate_memory){
        sample->value= DDS_String_alloc ((256));
        if (sample->value == NULL) {
            return RTI_FALSE;
        }

    } else {
        if (sample->value!= NULL) {
            sample->value[0] = '\0';
        }
    }

    if (allocParams->allocate_memory) {
        DDS_ShortSeq_initialize(&sample->more_values  );
        if (!DDS_ShortSeq_set_maximum(&sample->more_values , (100))) {
            return RTI_FALSE;
        }
    } else {
        DDS_ShortSeq_set_length(&sample->more_values, 0);
    }
    return RTI_TRUE;
} 

As you can see, it should allocate a new string.

Alex

Offline
Last seen: 5 years 9 months ago
Joined: 10/01/2015
Posts: 17

The problem is I do not want to allocate memory, only to initialize the top-level, so I set allocParams to FALSE. The existing value for smple->value is junk (not NULL) which causes '\0' to get written to un-allcoated memory.

I am also doing this in generic/templated code. I can't set the fields directly, as I want my function to work for any generated type.

Anyway, I think I solved my problem: The initialization should be: Type f = Type();

Related: the reason I'm trying to get a zerod-out, non-allocated object is to pass it to unregister_instance where I already have a valid instance handle. The docs for unregister_instance say the data may be NULL in this case, but the api is pass-by-reference (not pointer) so I have to give it somthing. It is crashing if there is junk in the data object passed.