简体   繁体   中英

C++ variadic parameters issue

Take a look at this code:

StdAfx.h:

#pragma once

#include <stdarg.h>

template<class T>
class DArray {
private:
    T* elements;
    int dimensions, length;
    int* lengths;

public:
    DArray() {
        dimensions = 0;
        length = 0;
    }

    DArray(int dims, ...) {
        va_list args;
        va_start(args, dims);
        dimensions = dims;
        lengths = new int[dims];
        length = 1;
        for (int i = 0; i < dims; i++) {
            lengths[i] = va_arg(args, int);
            length *= lengths[i];
        }
        va_end(args);
        elements = new T[length];
    }

    T get(...) {
        va_list args;
        va_start(args, dimensions);
        int weight = 1;
        int index = va_arg(args, int);
        for (int i = 1; i < dimensions; i++) {
            weight *= lengths[i - 1];
            index += va_arg(args, int) * weight;
        }
        va_end(args);
        return elements[index];
    }

    void set(T value, ...) {
        va_list args;
        va_start(args, dimensions);
        int weight = 1;
        int index = va_arg(args, int);
        for (int i = 1; i < dimensions; i++) {
            weight *= lengths[i - 1];
            index += va_arg(args, int) * weight;
        }
        va_end(args);
        elements[index] = value;
    }

    ~DArray() {
        if (lengths != nullptr)
            delete[] lengths;
        //thanks to an answer pointing out I forgot to add this part:
        if (elements != nullptr)
            delete[] elements;
    }
};

Main.cpp:

#include "stdafx.h"
#include <iostream>

DArray<int> generateRandomMatrix(int columns, int rows) {
    int x, y;
    DArray<int> matrix = DArray<int>(2, columns, rows);
    for (y = 0; y < rows; y++) {
        for (x = 0; x < columns; x++)
            matrix.set(rand(), x, y);
    }
    return matrix;
}

int main() {
    int x, y;
    DArray<int> matrix;
    do {
        matrix = generateRandomMatrix(10, 5);
        for (y = 0; y < 5; y++) {
            for (x = 0; x < 10; x++)
                printf("%d", matrix.get(x, y));
        }
        printf("\n\nPress Enter to restart...\n");
        getchar();
    } while (true);
    return 0;
}

For some reason, which for the life of me I cannot figure out, when matrix.set() is called from inside generateRandomMatrix(), the index variable has a negative value of -462266869 which is causing an index out of bounds exception.

How can index be negative if only positive parameters are passed to the function?

(Here is a screenshot of the Local Variables watch-window for what it's worth: http://i.imgur.com/LfGQ8OF.png )

In the member function set() ,

va_start(args, dimensions);

should be

va_start(args, value);

generateRandomMatrix returns DArray<int> but you don't have operator = nor copy constructor.

In such as case the return just copy the local class but then the destructor (of the local DArray matrix) been called and delete the allocations.

To resolve it, You should implement copy constructor and operator =. if you are using c++11 consider also move operator.

BTW: you have memory leak since the elements array didn't deleted.

The problem has been solved and I would like to thank the 2 answers I have got. Two things had to be fixed:

  1. First, va_start(args, value) should have been used as va_start apparently takes the last parameter that was explicitly specified as a second parameter.

The new methods are:

T get(int index, ...) {
    va_list args;
    va_start(args, index);
    int weight = 1;
    for (int i = 1; i < dimensions; i++) {
        weight *= lengths[i - 1];
        index += va_arg(args, int) * weight;
    }
    va_end(args);
    return elements[index];
}

void set(T value, ...) {
    va_list args;
    va_start(args, value);
    int weight = 1;
    int index = va_arg(args, int);
    for (int i = 1; i < dimensions; i++) {
        weight *= lengths[i - 1];
        index += va_arg(args, int) * weight;
    }
    va_end(args);
    elements[index] = value;
}
  1. The destructor was being called, breaking the function. Modifying the main method and generateRandMatrix() to use DArray* instead of DArray lumped together with the first fix solved the problem! :D

A big thanks to all those who spent their time on this question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM