简体   繁体   English

试图传递2D字符数组,但出现垃圾

[英]Trying to pass 2D array of chars, but getting garbage

I am trying to parse a std::string , split it, and then store it in a 2D char array. 我正在尝试解析std::string ,将其拆分,然后将其存储在2D char数组中。 The first row of this array, will contain the total number of rows. 该数组的第一行将包含总行数。 I dynamically allocate the array inside the getC_strings() function, and when I print it, I get the expected results. 我在getC_strings()函数内部动态分配了数组,当我打印它时,得到了预期的结果。 However, when I am printing again from the main() , I get garbage, for rows 0, 2. What am I doing wrong? 但是,当我再次从main()打印时,对于行0、2,我得到了垃圾,我在做什么错呢?

#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of
#include <boost/algorithm/string/split.hpp>          // Include for boost::split

using namespace std;

/**
*
* @param input a string separated by spaces
* @param numArgs_ an int
* @param cargs a const char ** something.  Pass it by its address aka &something.
*/
static inline void getC_strings(const std::string & input, int & numArgs_, const char *** cargs) {

    std::vector<std::string> args;
    boost::split(args, input, boost::is_any_of(" "), boost::token_compress_on);
    numArgs_ = int(args.size());
    *cargs = new const char* [numArgs_ + 1];


    // store the number of rows at the first row
    (*cargs)[0] = new char[to_string(numArgs_).size()];
    (*cargs)[0] = to_string(numArgs_).c_str();

    // write the characters from the vector per row
    int ind = 0;
    for(auto const &v:args) {
        ind++;
        (*cargs)[ind] = new char [int(v.size())];
        if((*cargs)[ind] == NULL) std::cout << "OUT OF MEMORY! " << std::endl;
        (*cargs)[ind] = const_cast<char*>(v.c_str());
    }


    for(int i = 0; i < numArgs_; ++i) {
        std::cout << i << " " << (*cargs)[i] << std::endl;
    }

}


int main () {

    string arg = "test ./MyDirectoryName/OPQ_Arksoatn.txt 1 SOMETHING 1 2 3 4 5 6 7";
    int numCargs = 0;
    const char ** cargs;
    getC_strings(arg, numCargs, &cargs);

    cout << "  ==============================================" << endl;
    for(int i = 0; i < numCargs; ++i) {
        std::cout << i << " " << cargs[i] << std::endl;
    }

    return 0;
}

OUTPUT: OUTPUT:

    0 11
    1 test
    2 ./MyDirectoryName/OPQ_Arksoatn.txt
    3 1
    4 SOMETHING
    5 1
    6 2
    7 3
    8 4
    9 5
    10 6
    ==============================================
    0 ��`
    1 test
    2 `��
    3 1
    4 SOMETHING
    5 1
    6 2
    7 3
    8 4
    9 5
    10 6

You can try this method that does not leak memory. 您可以尝试这种不会泄漏内存的方法。 It is crafted from the solution found here . 它是根据此处找到的解决方案制作的。

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of
#include <boost/algorithm/string/split.hpp>          // Include for boost::split

using namespace std;

class CharStarWrapper
{
    private:
        typedef std::vector<char> CharArray;
        typedef std::list<CharArray> StringList;
        typedef std::vector<const char *> ArgList;
        const char** m_Args;
        StringList m_sList;
        ArgList m_cStrings;

    public:
        CharStarWrapper(const std::string & input) : m_Args(nullptr)
        {
            std::vector<std::string> args;
            boost::split(args, input, boost::is_any_of(" "), boost::token_compress_on);
            for (auto const &v : args)
            {
                // create an array of char and place on list
                m_sList.push_back(CharArray(v.begin(), v.end()));

                // null terminate this entry
                m_sList.back().push_back(0);

                // add the pointer to this entry to the vector of const char *.
                m_cStrings.push_back(&m_sList.back()[0]);
            }
            m_Args = m_cStrings.data();
        }

        const char** getArgs() { return m_Args;  }
        int getArgCount() const { return static_cast<int>(m_cStrings.size()); }
};

void fake_main(int argc, const char **argv)
{
   std::cout << "The number of arguments is " << argc << "\n";
   for (int i = 0; i < argc; ++i) 
        std::cout << argv[i] << "\n";
}

int main() {
    string arg = "test ./MyDirectoryName/OPQ_Arksoatn.txt 1 SOMETHING 1 2 3 4 5 6 7";
    CharStarWrapper wrapper(arg);
    fake_main(wrapper.getArgCount(), wrapper.getArgs());        
}

Live Example 现场例子

Basically, we wrap the const char** in a class. 基本上,我们将const char**包装在一个类中。 This class maintains the dynamic array of strings, and merely provides public member functions to return the const char** as well as the number of arguments. 此类维护字符串的动态数组,并且仅提供public成员函数以返回const char**以及参数的数量。 A call to a "fake" main() function demonstrates the usage. 调用“假” main()函数演示了用法。

There are no calls to new[] , delete[] , strdup , etc. that would require calls to the deallocation routines to avoid memory leaks. 没有对new[]delete[]strdup等的调用,这些调用需要对释放例程进行调用以避免内存泄漏。 When the wrapper goes out of scope, all of the memory is cleaned up automatically. 当包装超出范围时,将自动清除所有内存。

Note that this solution relies on the wrapper object not going out of scope for the lifetime you will be using the const char ** value. 请注意,此解决方案依赖于包装对象在使用const char **值的生命周期内不会超出范围。 The reason is that CharStarWrapper maintains the infrastructure, and destroying the infrastructure while using it will be incorrect. 原因是CharStarWrapper维护基础结构,并且在使用基础结构时将其破坏是不正确的。

In a couple of places: 在几个地方:

// store the number of rows at the first row
(*cargs)[0] = new char[to_string(numArgs_).size()];
(*cargs)[0] = to_string(numArgs_).c_str();

and

   // Similar code that allocates then ignores some space
   (*cargs)[ind] = const_cast<char*>(v.c_str());

You are carrying off a pointer to an internal part of a std::string. 您正在执行一个指向std :: string内部部分的指针。 You need to duplicate this into your array to walk off with it in your char array structure. 您需要将其复制到数组中,才能在char数组结构中使用它。 (see strdup). (请参阅strdup)。

Replace with: 用。。。来代替:

(*cargs)[0] = strdup(to_string(numArgs_).c_str());

and

   (*cargs)[ind] = strdup(v.c_str());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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