Changseok Ma
Changseok Ma

Reputation: 89

How to put values to 3d array which is dynamically allocated in C++

I am writing some codes to understand how dynamically allocating 3d array works in C++. This is just a sample code I wrote.

#include <iostream>
#include <fstream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstdio>
using namespace std;

int Na = 3;
int Nd = 3;
int Ny = 3;

int main() {

    double*** tempmax = new double** [Na];
    for (int i = 0; i < Na; i++) {
        tempmax[i] = new double* [Nd];
        for (int j = 0; j < Nd; j++) {
            tempmax[i][j] = new double[Ny];
            fill_n(tempmax[i][j], Ny, 2);
        }
    }
    
    tempmax[2][2][1] = 3;
    
}

First, I allocate 'tempmax' 3d array filled with 2. Then I was trying to change the value to 3 for tempmax[2][2][1]. Then I got this warning message "Warning C6386 Buffer overrun while writing to 'tempmax': the writable size is 'int Na*8' bytes, but '24' bytes might be written."

Some people say that sometimes this is just a false warning. And I just want to check whether this is false or there is some basic mistake I am making here.

Upvotes: 0

Views: 103

Answers (2)

Aykhan Hagverdili
Aykhan Hagverdili

Reputation: 29985

Wrap it in a class, or get a library that does. What you're doing is not very optimal as you do many allocations. Also, you'll be chasing pointers around, which is also not cache friendly. Here's a minimal example:

#include <cassert>
#include <cstdio>
#include <memory>

template <class T>
class matrix_3d {
private:
    std::unique_ptr<T[]> m_data;
    std::size_t m_cx, m_cy, m_cz;

public:
    matrix_3d(std::size_t const cx,
              std::size_t const cy,
              std::size_t const cz)
        : m_data{ new T[cx * cy * cz] }
        , m_cx{ cx }
        , m_cy{ cy }
        , m_cz{ cz }
    {}

    T& get(std::size_t const x,
        std::size_t const y,
        std::size_t const z) noexcept {
        // use the const version
        return const_cast<T&>(static_cast<matrix_3d const*>(this)->get(x, y, z));
    }

    T const& get(std::size_t const x,
        std::size_t const y,
        std::size_t const z) const noexcept {
        auto const idx = (z * m_cx * m_cy) + (y * m_cx) + x;
        assert(idx < m_cx * m_cy * m_cz);
        return m_data[idx];
    }
};

int main() {
    std::size_t const cx = 4;
    std::size_t const cy = 3;
    std::size_t const cz = 2;

    matrix_3d<int> m(cx, cy, cz);

    int n = 0;
    for (std::size_t x = 0; x < cx; ++x) {
        for (std::size_t y = 0; y < cy; ++y) {
            for (std::size_t z = 0; z < cz; ++z) {
                m.get(x, y, z) = (n++);
            }
        }
    }

    for (std::size_t x = 0; x < cx; ++x) {
        for (std::size_t y = 0; y < cy; ++y) {
            for (std::size_t z = 0; z < cz; ++z) {
                printf("%d\n", m.get(x, y, z));
            }
        }
    }
}

You should additionally consider adding move/copy constructors and assignment operators.

Upvotes: 0

Ext3h
Ext3h

Reputation: 6391

It's a false warning, but a justified one. You should have made Na, Nd and Ny at least const or better constexpr.

As they are, they are global variables visible and modifiable by other compilation units. For the compiler the logic goes "they might change to be smaller than 3". Const-correctness also helps with that diagnostic.

Besides, you are leaking memory. Everything you allocate with new you must delete again. Don't ever get used to omitting that.

Besides, that warning is actually in /W4 or /Wall. Most of the warnings added beyond /W3 usually hardly actually warn about real, immediate issues, but are mostly in the "things could go wrong under condition X" category.

Upvotes: 3

Related Questions