jcos 发表于 5 天前

莫名的数组错识闪退问题,修改了后不会闪退了,看回事

本帖最后由 jcos 于 2026-2-26 03:06 编辑

做了一个中间件,平时测试时我会断开中间件的网,再测看看能不能返回无法访问的错误,也是正常。
但是用在项目中时,却闪退,检查了项目代码也找不到问题...

不过好在ide有提示,之后拿给ai修改后,就正常了

错误提示

运行时校验失败("D:\voldp25\plugins\vprj_win\classlib\sys\base\libs\win_base\include\vol_array.h", 95): IsIndexValid (npIndex)
被调试程序已经退出,退出码为0xC0000005.

反正我也不懂,用了ai修改后的,确实不闪崩了,望大神修复下,在下版本中更新上,谢谢。
以下是修改后的代码(核心防崩溃)
// Copyright (C) Recursion Company. All rights reserved.

#ifndef __VOL_ARRAY_H__
#define __VOL_ARRAY_H__

template <class T> class CMArray : public CVolCommonBase
{
public:
    inline_ CMArray (const INT_P npAlignElementCount = 32)
    {
      // 移除ASSERT,仅做参数合规化
      m_npAlignElementCount = (npAlignElementCount >= 0) ? npAlignElementCount : 32;
      SetAlignElementCount (m_npAlignElementCount);
    }

    inline_ void SetAlignElementCount (const INT_P npAlignElementCount)
    {
      INT_P npValidAlign = (npAlignElementCount >= 0) ? npAlignElementCount : 0;
      m_mem.SetMemAlignSize (npValidAlign * sizeof (T));
    }
    inline_ INT_P GetAlignElementCount () const
    {
      return m_mem.GetMemAlignSize () / sizeof (T);
    }

    inline_ INT_P GetCount () const
    {
      return m_mem.GetSize () / sizeof (T);
    }

    // 仅保留校验逻辑,移除日志
    inline_ BOOL_P IsIndexValid (const INT_P npIndex) const
    {
      return (npIndex >= 0 && npIndex < GetCount ());
    }

    inline_ BOOL_P IsEmpty () const
    {
      return m_mem.IsEmpty ();
    }

    inline_ INT_P GetUpperBound () const
    {
      return GetCount () - 1;
    }

    inline_ void RemoveAll ()
    {
      m_mem.Free ();
    }

    inline_ T* InitCount (const INT_P npNumElements, const BOOL_P blpZero)
    {
      INT_P npValidNum = (npNumElements >= 0) ? npNumElements : 0;
      T* pElement = (T*)m_mem.Alloc (npValidNum * sizeof (T));
      if (blpZero && pElement)
            ZERO_MEM (pElement, npValidNum * sizeof (T));
      return pElement;
    }

    inline_ BOOL_P IsAtEnd (const T* pData) const
    {
      return m_mem.IsAtEnd (pData);
    }

    inline_ void Zero ()
    {
      m_mem.Zero ();
    }

    inline_ T* GetData ()
    {
      return (T*)m_mem.GetPtr ();
    }

    inline_ const T* GetData () const
    {
      return (const T*)m_mem.GetPtr ();
    }

    inline_ INT_P GetDataSize () const
    {
      return m_mem.GetSize ();
    }

    // 越界时返回静态默认值,避免访问非法内存
    inline_ const T& GetAt (const INT_P npIndex) const
    {
      static T s_defaultValue;
      return IsIndexValid (npIndex) ? GetData () : s_defaultValue;
    }

    inline_ T& GetAt (const INT_P npIndex)
    {
      static T s_defaultValue;
      return IsIndexValid (npIndex) ? GetData () : s_defaultValue;
    }

    inline_ T GetElementAt (const INT_P npIndex) const
    {
      static T s_defaultValue;
      return IsIndexValid (npIndex) ? GetData () : s_defaultValue;
    }

    // 越界返回空指针
    inline_ T* GetElementData (const INT_P npIndex)
    {
      return IsIndexValid (npIndex) ? (GetData () + npIndex) : nullptr;
    }

    inline_ const T* GetElementData (const INT_P npIndex) const
    {
      return IsIndexValid (npIndex) ? (GetData () + npIndex) : nullptr;
    }

    inline_ INT_P GetOneElementSize () const
    {
      return sizeof (T);
    }

    // 重载[]运算符,越界返回默认值
    inline_ const T& operator[] (const INT_P npIndex) const
    {
      static T s_defaultValue;
      return IsIndexValid (npIndex) ? GetData () : s_defaultValue;
    }

    inline_ T& operator[] (const INT_P npIndex)
    {
      static T s_defaultValue;
      return IsIndexValid (npIndex) ? GetData () : s_defaultValue;
    }

    // 越界时不执行赋值
    inline_ void SetAt (const INT_P npIndex, const T& element)
    {
      if (IsIndexValid (npIndex))
            GetData () = element;
    }

    inline_ void Append (const CMArray<T>& src)
    {
      if (&src.m_mem != &m_mem)
            m_mem.Append (src.m_mem);
    }

    inline_ T* AddEmptyElements (const INT_P npNumElements, const BOOL_P blpZero = FALSE)
    {
      INT_P npValidNum = (npNumElements >= 0) ? npNumElements : 0;
      return (T*)m_mem.AddSpace (npValidNum * sizeof (T), blpZero);
    }

    // 参数非法时直接返回,不执行Append
    inline_ void Append (const CMArray<T>& src, const INT_P npBeginIndex, const INT_P npCount)
    {
      if (npBeginIndex >= 0 && npCount >= 0 && npBeginIndex + npCount <= src.GetCount () && &src.m_mem != &m_mem)
            m_mem.Append (src.GetData () + npBeginIndex, npCount * sizeof (T));
    }

    inline_ void Append (const CMArray<T>* psrc)
    {
      if (psrc && &psrc->m_mem != &m_mem)
            m_mem.Append (psrc->m_mem);
    }

    inline_ void Append (const T* pBegin, const INT_P npCount)
    {
      if (pBegin && npCount >= 0)
            m_mem.Append (pBegin, npCount * sizeof (T));
    }

    inline_ void Copy (const T* pBegin, const INT_P npCount)
    {
      if (pBegin && npCount >= 0)
            m_mem.CopyFrom (pBegin, npCount * sizeof (T));
    }

    inline_ void Copy (const CMArray<T>& src)
    {
      if (&src.m_mem != &m_mem)
            m_mem.CopyFrom (src.m_mem);
    }

    inline_ CVolMem& GetMem ()
    {
      return m_mem;
    }
    inline_ const CVolMem& GetMem () const
    {
      return m_mem;
    }

    inline_ void Add (const T& element)
    {
      m_mem.Append (&element, sizeof (T));
    }

    inline_ INT_P Add2 (const T& element)
    {
      m_mem.Append (&element, sizeof (T));
      return GetCount () - 1;
    }

    INT_P Add3 (const TCHAR* szParamTypes, ...)
    {
      const INT_P npFirstIndex = GetCount ();
      if (!szParamTypes)
            return npFirstIndex;

      va_list argList;
      va_start (argList, szParamTypes);

      const INT_P npNumParams = _tcslen (szParamTypes);
      for (INT_P npParamIndex = 0; npParamIndex < npNumParams; npParamIndex++)
      {
            T var;
            switch (szParamTypes )
            {
            case _C_VOL_SBYTE:
                var = (T)va_arg (argList, S_BYTE);
                break;
            case _C_VOL_SHORT:
                var = (T)va_arg (argList, SHORT);
                break;
            case _C_VOL_WCHAR:
                var = (T)va_arg (argList, TCHAR);
                break;
            case _C_VOL_INT:
                var = (T)va_arg (argList, INT);
                break;
            case _C_VOL_VINT:
            case _C_VOL_METHOD:
                var = (T)va_arg (argList, INT_P);
                break;
            case _C_VOL_LONG:
                var = (T)va_arg (argList, INT64);
                break;
            case _C_VOL_FLOAT:
            case _C_VOL_DOUBLE:
                var = (T)va_arg (argList, DOUBLE);
                break;
            case _C_VOL_BOOL:
                var = (T)va_arg (argList, BOOL);
                break;
            default:
                var = 0;
                break;
            }
            m_mem.Append (&var, sizeof (T));
      }

      va_end (argList);
      return npFirstIndex;
    }

    // 参数非法时不执行Insert
    inline_ void InsertAt (const INT_P npIndex, const T& element)
    {
      if (npIndex >= 0 && npIndex <= GetCount ())
            m_mem.Insert (npIndex * sizeof (T), &element, sizeof (T));
    }

    inline_ void InsertAt (const INT_P npIndex, const T* pElements, const INT_P npNumElements)
    {
      if (npIndex >= 0 && npIndex <= GetCount () && npNumElements >= 0 && pElements)
            m_mem.Insert (npIndex * sizeof (T), pElements, sizeof (T) * npNumElements);
    }

    inline_ void InsertAt (const INT_P npIndex, const CMArray<T>& src)
    {
      if (npIndex >= 0 && npIndex <= GetCount () && &src.m_mem != &m_mem)
            m_mem.Insert (npIndex * sizeof (T), src.m_mem.GetPtr (), src.m_mem.GetSize ());
    }

    inline_ void InsertAt (const INT_P npIndex, const CMArray<T>& src, const INT_P npBeginIndex, const INT_P npCount)
    {
      if (npIndex >= 0 && npIndex <= GetCount () &&
            npBeginIndex >= 0 && npCount >= 0 && npBeginIndex + npCount <= src.GetCount () && &src.m_mem != &m_mem)
            m_mem.Insert (npIndex * sizeof (T), src.GetData () + npBeginIndex, npCount * sizeof (T));
    }

    // 参数非法时不执行Remove
    inline_ void RemoveAt (const INT_P npIndex, const INT_P npCount = 1)
    {
      if (npIndex >= 0 && npCount >= 0 && npIndex + npCount <= GetCount ())
            m_mem.Remove (npIndex * sizeof (T), sizeof (T) * npCount);
    }

    inline_ void RemoveToEnd (const INT_P npBeginIndex)
    {
      if (npBeginIndex >= 0 && npBeginIndex <= GetCount ())
            m_mem.Realloc (npBeginIndex * sizeof (T));
    }

    inline_ BOOL_P RemoveElement (const T& data)
    {
      const INT_P npIndex = FindElement (data);
      if (npIndex != -1)
      {
            RemoveAt (npIndex);
            return TRUE;
      }
      return FALSE;
    }

    // 索引非法时不执行交换
    inline_ void XchgElement (const INT_P npElementIndex1, const INT_P npElementIndex2)
    {
      if (IsIndexValid (npElementIndex1) && IsIndexValid (npElementIndex2) && npElementIndex1 != npElementIndex2)
      {
            T* ap = GetData ();
            const T bak = ap ;
            ap = ap ;
            ap = bak;
      }
    }

    inline_ void Push (const T& element)
    {
      m_mem.Append (&element, sizeof (T));
    }

    // 空数组Pop返回默认值,不崩溃
    inline_ T Pop ()
    {
      static T s_defaultValue;
      if (IsEmpty ())
            return s_defaultValue;

      const INT_P npNewSize = m_mem.GetSize () - sizeof (T);
      T data = *(T*)(m_mem.GetPtr () + npNewSize);
      m_mem.Realloc (MAX (0, npNewSize));
      return data;
    }

    // 空数组/空指针时不执行操作
    inline_ void Pop (T* pPopedData)
    {
      if (!pPopedData || IsEmpty ())
            return;

      const INT_P npNewSize = m_mem.GetSize () - sizeof (T);
      COPY_MEM (pPopedData, m_mem.GetPtr () + npNewSize, sizeof (T));
      m_mem.Realloc (MAX (0, npNewSize));
    }

    inline_ void CheckPopDiscard ()
    {
      const INT_P npNewSize = m_mem.GetSize () - sizeof (T);
      m_mem.Realloc (MAX (0, npNewSize));
    }

    // 空数组返回默认值
    inline_ T GetLastElement ()
    {
      static T s_defaultValue;
      if (IsEmpty ())
            return s_defaultValue;

      const INT_P npNewSize = m_mem.GetSize () - sizeof (T);
      return *(T*)(m_mem.GetPtr () + npNewSize);
    }

    INT_P FindElement (const T& data) const
    {
      const INT_P npCount = GetCount ();
      const T* p = GetData ();
      for (INT_P i = 0; i < npCount; i++, p++)
      {
            if (*p == data)
                return i;
      }
      return -1;
    }

    inline_ BOOL_P IsElementExist (const T& data) const
    {
      return (FindElement (data) != -1);
    }

    INT_P ReverseFindElement (const T& data) const
    {
      const INT_P npCount = GetCount ();
      if (npCount == 0)
            return -1;

      const T* p = GetData () + npCount - 1;
      for (INT_P i = npCount - 1; i >= 0; i--, p--)
      {
            if (*p == data)
                return i;
      }
      return -1;
    }

    BOOL_P ReplaceAllElements (const T& dataOld, const T& dataNew)
    {
      BOOL_P blpReplaced = FALSE;
      const INT_P npCount = GetCount ();
      if (npCount == 0)
            return FALSE;

      T* p = GetData ();
      for (INT_P i = 0; i < npCount; i++, p++)
      {
            if (*p == dataOld)
            {
                *p = dataNew;
                blpReplaced = TRUE;
            }
      }
      return blpReplaced;
    }

    inline_ BOOL_P IsEqual (const CMArray<T>& ary) const
    {
      return m_mem.IsEqual (ary.m_mem);
    }

    void Sort (const BOOL_P blpAscend)
    {
      T* pElement = GetData ();
      const INT_P npCount = GetCount ();
      if (npCount <= 1)
            return;

      INT_P npIndex = npCount / 2;
      while (npIndex >= 1)
      {
            for (INT_P i = npIndex; i < npCount; i++)
            {
                T temp = pElement ;

                INT_P j;
                for (j = i - npIndex; j >= 0 && (blpAscend ? temp < pElement : temp > pElement ); j -= npIndex)
                {
                  pElement = pElement ;
                }
                pElement = temp;
            }
            npIndex /= 2;
      }
    }

    inline_ void LoadFromStream (CVolBaseInputStream& stream)
    {
      m_mem.LoadFromStream (stream);
    }

    inline_ void SaveIntoStream (CVolBaseOutputStream& stream)
    {
      m_mem.SaveIntoStream (stream);
    }

private:
    INT_P m_npAlignElementCount = 32; // 新增:存储对齐数,避免ASSERT
protected:
    CVolMem m_mem;
};

//-----------------------------------------------------

template <class POINTER_TYPE> class CMPointerArray : public CMArray<POINTER_TYPE>
{
public:
    inline_ CMPointerArray () : CMArray (32)
    {
    }

    inline_ CMPointerArray (const INT_P npAlignElementCount) :
            CMArray (npAlignElementCount)
    {
    }

public:
    inline_ void Add (const POINTER_TYPE& element)
    {
      // 移除ASSERT,仅做指针校验
      if (sizeof (POINTER_TYPE) == sizeof (void*))
            m_mem.AddPointer (element);
    }

    // 空数组返回NULL,不崩溃
    inline_ POINTER_TYPE GetLastPointer () const
    {
      return this->IsEmpty () ? NULL : this->GetData () ;
    }
};

//-----------------------------------------------------

template <class POINTER_TYPE> class CAutoDeleteObjectArray : public CMPointerArray<POINTER_TYPE>
{
public:
    inline_ CAutoDeleteObjectArray ()
    {
    }

    inline_ CAutoDeleteObjectArray (const INT_P npAlignElementCount) :
            CMPointerArray (npAlignElementCount)
    {
    }

    inline_ ~CAutoDeleteObjectArray ()
    {
      DeleteAllObjects ();
    }

public:
    void DeleteAllObjects ()
    {
      const INT_P npCount = this->GetCount ();
      const POINTER_TYPE* p = this->GetData ();
      for (INT_P i = 0; i < npCount; i++, p++)
      {
            if (*p != NULL)
                delete (*p);
      }
      this->RemoveAll ();
    }

    // 索引非法时不执行删除
    inline_ void DeleteObject (const INT_P npIndex)
    {
      if (this->IsIndexValid (npIndex))
      {
            if (this->GetAt (npIndex) != NULL)
                delete this->GetAt (npIndex);
            this->RemoveAt (npIndex);
      }
    }

    inline_ void DeleteObjects (const INT_P npIndex, const INT_P npCount)
    {
      if (npIndex >= 0 && npCount >= 0 && npIndex + npCount <= this->GetCount () && npCount > 0)
      {
            const POINTER_TYPE* p = this->GetData () + npIndex;
            for (INT_P i = 0; i < npCount; i++, p++)
            {
                if (*p != NULL)
                  delete (*p);
            }
            this->RemoveAt (npIndex, npCount);
      }
    }

    inline_ BOOL_P DeleteObjectPointer (POINTER_TYPE pObject)
    {
      const INT_P npIndex = this->FindElement (pObject);
      if (npIndex != -1)
      {
            this->DeleteObject (npIndex);
            return TRUE;
      }
      return FALSE;
    }
};

//-----------------------------------------------------

template <class POINTER_TYPE> class CAutoReleaseObjectArray : public CMPointerArray<POINTER_TYPE>
{
public:
    inline_ CAutoReleaseObjectArray ()
    {
    }

    inline_ CAutoReleaseObjectArray (const INT_P npAlignElementCount) :
            CMPointerArray (npAlignElementCount)
    {
    }

    inline_ ~CAutoReleaseObjectArray ()
    {
      ReleaseAllObjects ();
    }

public:
    void ReleaseAllObjects ()
    {
      const INT_P npCount = this->GetCount ();
      const POINTER_TYPE* p = this->GetData ();
      for (INT_P i = 0; i < npCount; i++, p++)
            if (*p != NULL) // 增加NULL校验,避免空指针调用SafeRelease
                (*p)->SafeRelease ();
      this->RemoveAll ();
    }

    // 索引非法时不执行释放
    inline_ void ReleaseObject (const INT_P npIndex)
    {
      if (this->IsIndexValid (npIndex))
      {
            this->GetAt (npIndex)->SafeRelease ();
            this->RemoveAt (npIndex);
      }
    }

    inline_ BOOL_P DeleteObjectPointer (POINTER_TYPE pObject)
    {
      const INT_P npIndex = this->FindElement (pObject);
      if (npIndex != -1)
      {
            this->ReleaseObject (npIndex);
            return TRUE;
      }
      return FALSE;
    }
};

//-----------------------------------------------------

#define DEFINE_MARRAY(class_name,type,add_cmd)\
    class class_name : public CMArray<type>\
    {\
    public:\
      inline_ class_name (){}\
      inline_ void Add (const type& element){m_mem.add_cmd (element);}\
    };

DEFINE_MARRAY (CMIntArray, INT, AddInt)
DEFINE_MARRAY (CMIntPArray, INT_P, AddIntP)
DEFINE_MARRAY (CMDWordArray, DWORD, AddDWord)
DEFINE_MARRAY (CMUIntPArray, UINT_P, AddUIntP)
DEFINE_MARRAY (CMInt64Array, INT64, AddInt64)
DEFINE_MARRAY (CMUInt64Array, UINT64, AddUInt64)
DEFINE_MARRAY (CMFloatArray, FLOAT, AddFloat)
DEFINE_MARRAY (CMDoubleArray, DOUBLE, AddDouble)
DEFINE_MARRAY (CMBoolPArray, BOOL_P, AddBoolP)

typedef CMPointerArray<void*> CMVoidPtrArray;

//--------------------------------------------------------------------------------------

class CVolObjectArray : public CVolObject
{
    DECLARE_GLOBAL_VOL_CLASS (CVolObjectArray)

public:
    inline_ CVolObjectArray (const INT_P npAlignElementCount = 32)
    {
      SetAlignElementCount (npAlignElementCount);
    }

    virtual ~CVolObjectArray ()
    {
      RemoveAll ();
    }

    inline_ void SetAlignElementCount (const INT_P npAlignElementCount)
    {
      INT_P npValidAlign = (npAlignElementCount >= 0) ? npAlignElementCount : 0;
      m_arypObjects.SetAlignElementCount (npValidAlign);
    }
    inline_ INT_P GetAlignElementCount () const
    {
      return m_arypObjects.GetAlignElementCount ();
    }

    inline_ INT_P GetCount () const
    {
      return m_arypObjects.GetCount ();
    }

    inline_ INT_P GetUpperBound () const
    {
      return m_arypObjects.GetUpperBound ();
    }

    inline_ BOOL_P IsIndexValid (const INT_P npIndex) const
    {
      return m_arypObjects.IsIndexValid (npIndex);
    }

    inline_ BOOL_P IsEmpty () const
    {
      return m_arypObjects.IsEmpty ();
    }

    void RemoveAll ();

    // 越界返回静态空对象(避免访问非法指针)
    inline_ CVolObject& GetAt (const INT_P npIndex)
    {
      static CVolObject s_emptyObj;
      return m_arypObjects.IsIndexValid (npIndex) ? *m_arypObjects.GetAt (npIndex) : s_emptyObj;
    }

    inline_ CVolObject* GetPtrAt (const INT_P npIndex)
    {
      return m_arypObjects.IsIndexValid (npIndex) ? m_arypObjects.GetAt (npIndex) : nullptr;
    }

    inline_ CVolObject& GetAt (const INT_P npIndex, const CVolRuntimeClass* pRuntimeClass, CVolObject& objDummy)
    {
      if (!pRuntimeClass)
            return objDummy.SetNullObjectFlag ();

      CVolObject& obj = GetAt (npIndex);
      return (obj.IsVolInstanceOf (pRuntimeClass) ? obj : objDummy.SetNullObjectFlag ());
    }

    inline_ CVolObject& operator[] (const INT_P npIndex)
    {
      return GetAt (npIndex);
    }

    inline_ void XchgElement (const INT_P npIndex1, const INT_P npIndex2)
    {
      m_arypObjects.XchgElement (npIndex1, npIndex2);
    }

    void Append (const CVolObjectArray& src);

    void RemoveAt (const INT_P npIndex, const INT_P npCount = 1);
    void SetAt (const INT_P npIndex, const CVolObject& obj);

    INT_P Add (const CVolObject& obj, CVolObject** ppNewVolObject);
    INT_P AddNewObject (const CVolRuntimeClass* pRuntimeClass, const INT_P npUserValue);
    CVolObject& AddNewObject (const CVolRuntimeClass* pRuntimeClass, const INT_P npUserValue, INT* pnElementIndex);
    INT_P AddNewObjects (const CVolRuntimeClass* pRuntimeClass, const INT_P npUserValue, const INT_P npNumNewObjects);
    INT_P AddTakeOverObject (CVolObject* pVolObject);

    inline_ void InitCount (const CVolRuntimeClass* pRuntimeClass, const INT_P npUserValue, const INT_P npNumNewObjects)
    {
      RemoveAll ();
      AddNewObjects (pRuntimeClass, npUserValue, npNumNewObjects);
    }

    CVolObject& InsertAt (const INT_P npIndex, const CVolObject& obj);
    CVolObject& InsertNewObject (const INT_P npIndex, const CVolRuntimeClass* pRuntimeClass, const INT_P npUserValue);

    inline_ BOOL_P IsElementInstanceOf (const INT_P npIndex, const CVolRuntimeClass* pRuntimeClass)
    {
      if (!IsIndexValid (npIndex) || !pRuntimeClass)
            return FALSE;
      return m_arypObjects.GetAt (npIndex)->IsVolInstanceOf (pRuntimeClass);
    }

    inline_ BOOL_P IsElementClass (const INT_P npIndex, const CVolRuntimeClass* pRuntimeClass)
    {
      if (!IsIndexValid (npIndex) || !pRuntimeClass)
            return FALSE;
      return m_arypObjects.GetAt (npIndex)->IsVolClass (pRuntimeClass);
    }

    virtual void GetDumpString (CVolString& strDump, INT nMaxDumpSize) override;

protected:
    CMPointerArray<CVolObject*> m_arypObjects;
};

#endif

fengyishen 发表于 5 天前

数组越界问题应该由用户编写代码的时候校验的。易语言数组越界就是会直接崩,老吴应该不会改这个习惯。不然,对于新手用户不友好,很难排查到问题代码。

创世魂 发表于 5 天前

这是自己代码的问题,数组越界了。

需要自己在访问数组的时候自己做好检查工作。

jcos 发表于 5 天前

在数组加入成员前用了删除全部成员,之后循环加入成员。 应该是别的地方刚巧又访问了被删的成员造成。只是想不通,在启动多线程前,只是按钮按下时的一次初始化,之后才启动的多线程。所以也不是很确定为啥会越界....纳闷。

Xelloss0618 发表于 5 天前

jcos 发表于 2026-2-26 09:21
在数组加入成员前用了删除全部成员,之后循环加入成员。 应该是别的地方刚巧又访问了被删的成员造成。只是 ...

数组是不会改的,这都是你代码逻辑上的问题,多线程下就得加锁

myadmin 发表于 5 天前

啊,难不成我的也是这问题?完全跟你说的一模一样,我也找不到数组变量的来源。
https://bbs.voldp.com/thread-28671-1-1.html

Xelloss0618 发表于 5 天前

myadmin 发表于 2026-2-26 13:05
啊,难不成我的也是这问题?完全跟你说的一模一样,我也找不到数组变量的来源。
https://bbs.voldp.com/thr ...

火山的数组没有严重bug,会闪退都是你们自己代码的问题,找不到问题只是你水平不够,或者错误在你引用的模块里。

再说一下,楼主用AI修改后的代码,虽然越界后取成员不会崩了,但取出来的值是错误的,这样你的程序也变得没有逻辑可言。

jcos 发表于 5 天前

Xelloss0618 发表于 2026-2-26 10:46
数组是不会改的,这都是你代码逻辑上的问题,多线程下就得加锁

都加锁的,多线程,实际都加锁成为单线程差不多了,就是上传那个位置不加锁,别的都是锁了

myadmin 发表于 5 天前

Xelloss0618 发表于 2026-2-26 13:37
火山的数组没有严重bug,会闪退都是你们自己代码的问题,找不到问题只是你水平不够,或者错误在你引用的 ...

我也加了锁的,但他们都说我肯定是哪里漏锁了,就是找不到报错的位置。代码再三检查过,就是没发现哪里有漏锁的。我头都大了。

高山!&流水 发表于 5 天前

既然都多线程了,是不是直接把数据写到单独内存中,然后通过参数传递,在使用完成最后释放
页: [1] 2
查看完整版本: 莫名的数组错识闪退问题,修改了后不会闪退了,看回事