存储和恢复 std::vector 数据

Storing and Restoring std::vector data

我能够将 std::vector 数据存储和恢复到 NSData 并返回,但是,它会间歇性地工作。我最初发布了问题并接受了答案,因为它似乎在这里有效:

然而,有时它可以工作,有时它会导致 EXC_BAD_ACCESS 错误。我创建了一个示例 Xcode 项目来重现可以从此处下载的问题:

http://3DTOPO.com/VectorToData.zip

有时它会在测试迭代 33、47 或 105 时崩溃。

这是崩溃时的回溯:

* thread #1: tid = 0x1542ee1, 0x000000010d45e65e libsystem_platform.dylib`_platform_memmove$VARIANT$Nehalem + 254, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x7faf29000000)
frame #0: 0x000000010d45e65e libsystem_platform.dylib`_platform_memmove$VARIANT$Nehalem + 254
frame #1: 0x0000000109f46753 Foundation`_NSDataCreateVMDispatchData + 131
frame #2: 0x0000000109f44cf2 Foundation`-[_NSPlaceholderData initWithBytes:length:copy:deallocator:] + 230
frame #3: 0x0000000109f50902 Foundation`-[NSData(NSData) initWithBytes:length:] + 37
* frame #4: 0x0000000109ea2bfe VectorToData`storeContourData() + 574 at ViewController.mm:86
frame #5: 0x0000000109ea2943 VectorToData`-[ViewController viewDidLoad](self=0x00007faf3a10f410, _cmd="viewDidLoad") + 1443 at ViewController.mm:67
frame #6: 0x000000010af31984 UIKit`-[UIViewController loadViewIfRequired] + 1198
frame #7: 0x000000010af31cd3 UIKit`-[UIViewController view] + 27
frame #8: 0x000000010ae07fb4 UIKit`-[UIWindow addRootViewControllerViewIfPossible] + 61
frame #9: 0x000000010ae0869d UIKit`-[UIWindow _setHidden:forced:] + 282
frame #10: 0x000000010ae1a180 UIKit`-[UIWindow makeKeyAndVisible] + 42
frame #11: 0x000000010ad8eed9 UIKit`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4131
frame #12: 0x000000010ad95568 UIKit`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1769
frame #13: 0x000000010ad92714 UIKit`-[UIApplication workspaceDidEndTransaction:] + 188
frame #14: 0x000000010d78a8c8 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
frame #15: 0x000000010d78a741 FrontBoardServices`-[FBSSerialQueue _performNext] + 178
frame #16: 0x000000010d78aaca FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 45
frame #17: 0x000000010a905301 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #18: 0x000000010a8fb22c CoreFoundation`__CFRunLoopDoSources0 + 556
frame #19: 0x000000010a8fa6e3 CoreFoundation`__CFRunLoopRun + 867
frame #20: 0x000000010a8fa0f8 CoreFoundation`CFRunLoopRunSpecific + 488
frame #21: 0x000000010ad91f21 UIKit`-[UIApplication _run] + 402
frame #22: 0x000000010ad96f09 UIKit`UIApplicationMain + 171
frame #23: 0x0000000109ea237f VectorToData`main(argc=1, argv=0x00007fff55d5d6e0) + 111 at main.m:14
frame #24: 0x000000010d12a92d libdyld.dylib`start + 1

虽然首选使用 NSData,但我愿意使用 C++ 解决方案,但我发现我无法使用示例(例如 fstream 和 iostream)iOS。如果提供了 C++ 解决方案,请说明如何恢复数据以及如何存储数据。

如果您无法打开上面链接的项目,这里是相关代码,只需将其命名为 ViewController.mm 并将其放入新的单视图应用程序 Xcode 项目中:

//
//  ViewController.m
//  VectorToData
//
//  Created by jeshua on 8/27/16.
//  Copyright © 2016 3DTOPO Inc. All rights reserved.
//

#import "ViewController.h"
#import <vector>

using namespace std;

typedef vector<CGPoint> CGContour;
typedef vector<CGContour> CGContours;
const size_t cgContourSize = sizeof(CGContour);
static CGContours contoursVector;

@interface ViewController ()

@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];


    for (int testNumber = 0; testNumber < 1000; testNumber++) {

        NSLog(@"__________ Test Number: %d __________", testNumber);

        long numberOfContours = arc4random_uniform(2000) + 1000;

        contoursVector.clear();

        contoursVector = CGContours(numberOfContours);

        long numberOfBytesGenerated = 0;

        for( int contourNum = 0; (contourNum < numberOfContours); contourNum++ ) {

            long contourPointCount = arc4random_uniform(5000) + 1;

            CGContour thisContour = CGContour(contourPointCount);

            for( long pointNum = 0; pointNum < thisContour.size(); pointNum++ )
            {
                thisContour[pointNum] = CGPointMake(arc4random_uniform(800), arc4random_uniform(1200));
            }

            //This might seem redundant, but in my actual code the data is converted to CGPoints here
            //and is not already a CGPoint
            contoursVector[contourNum] = CGContour(contourPointCount);
            for( long pointNum = 0; pointNum < thisContour.size(); pointNum++ )
            {
                contoursVector[contourNum][pointNum] = thisContour[pointNum];
                numberOfBytesGenerated += cgContourSize;
            }

        }

        NSLog(@"  numberContoursGenerated: %lu, numberOfBytesGenerated: %lu", numberOfContours, numberOfBytesGenerated);

        storeContourData();

        NSLog(@"\n\n");
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

void storeContourData() {

    NSMutableArray<NSData *> *contourDataArray = [NSMutableArray new];

    long numberContoursStored = 0;
    long numberOfBytesStored = 0;

    for(const CGContour &contour : contoursVector)
    {

        // Both these data initializations seem to work the same
        NSData *data = [[NSData alloc] initWithBytes:&contour[0]
                                              length:contour.size() * cgContourSize];

//      NSData *data = [[NSData alloc] initWithBytes:contour.data()
//                                            length:contour.size() * cgContourSize];

        [contourDataArray addObject:data];

        numberContoursStored++;
        numberOfBytesStored += contour.size() * cgContourSize;
    }

    NSLog(@"  numberContoursStored:    %lu, numberOfBytesStored:    %lu", numberContoursStored, numberOfBytesStored);
}

@end

问题是轮廓byte大小计算错误,不是

contour.size() * cgContourSize; // sizeof(vector<CGPoint>)

但应该是

contour.size() * sizeof(CGPoint);

您无法预先计算矢量(或其他数据容器)的字节大小。

应该避免这样的陈述:

sizeof(vector<...>);

因为结果是vector对象的byte大小,而不是vector中数据的byte大小