
åæžã
ç§ãã¡ã¯æ©æ¢°åŠç¿ã䜿çšããŠãããžã§ã¯ãã®ãšã©ãŒãç¹°ãè¿ãæ¢ããŠããŸããããDeepSpeechãäŸå€ã§ã¯ãããŸããã§ããããã®ãããžã§ã¯ãã¯éåžžã«äººæ°ããããããåœç¶ã®ããšã§ãããã®èšäºã®å·çæç¹ã§ã¯ãGitHubã«ã¯ãã§ã«15,000ãè¶ ããæããããŸãã
ãã€ãã®ããã«ããã®èšäºã§åŒçšãããšã©ãŒã®æ€çŽ¢ã¯ãPVS-Studioéçã³ãŒãã¢ãã©ã€ã¶ãŒã䜿çšããŠå®è¡ãããŸããã
ãã®äœæ¥ã®ããã«ãDeepSpeechã¯TensorFlowã©ã€ãã©ãªã䜿çšããŸãããã®ã©ã€ãã©ãªã«é¢ããå¥ã®èšäºããã§ã«æžããŠããã®ã§ããã®ã©ã€ãã©ãªã®ã³ãŒãã®åæããªãã«ããŸããããã ãã䜿çšããæ®ãã®ã©ã€ãã©ãªã®åæã¯ãªãã«ããŸããã§ãããããã®çç±ã¯äœã§ããïŒãããžã§ã¯ãã«å«ããã©ã€ãã©ãªå ã®ãšã©ãŒãããããžã§ã¯ãå ã®ãšã©ãŒã«ãªããŸãããããã£ãŠãèªåã ãã§ãªãã䜿çšããŠãããµãŒãããŒãã£ã®ã³ãŒããåæãããšäŸ¿å©ã§ããããã«é¢ããè©³çŽ°ãªæèŠã¯ãæè¿ã®èšäºã§èªãããšãã§ããŸãã
ããã§ç°¡åãªç޹ä»ã¯çµããã§ãããšã©ãŒã®åæã«ç§»ããŸããããã¡ãªã¿ã«ãèšäºã®ã¿ã€ãã«ã§ç§ãå°ãã質åãžã®çããèŠã€ããããã«ããã«æ¥ãå ŽåïŒãªãnamespace stdã§æžãã¹ãã§ã¯ãªãã®ãïŒãããã«èšäºã®çµãããèŠãããšãã§ããŸããç¹ã«è峿·±ãäŸãããªããåŸ ã£ãŠããŸãïŒ
ã¢ãã©ã€ã¶ãŒã«ãã£ãŠçºè¡ããã10ã®è峿·±ãèŠåã®æŠèŠ
èŠå
1V773ãããŒã¿ããã€ã³ã¿ãè§£æŸããã«é¢æ°ãçµäºããŸãããã¡ã¢ãªãªãŒã¯ãçºçããå¯èœæ§ããããŸããç·šé-fst.h311
// EditFstData method implementations: just the Read method.
template <typename A, typename WrappedFstT, typename MutableFstT>
EditFstData<A, WrappedFstT, MutableFstT> *
EditFstData<A, WrappedFstT, MutableFstT>::Read(std::istream &strm,
const FstReadOptions &opts)
{
auto *data = new EditFstData<A, WrappedFstT, MutableFstT>();
// next read in MutabelFstT machine that stores edits
FstReadOptions edits_opts(opts);
....
std::unique_ptr<MutableFstT> edits(MutableFstT::Read(strm, edits_opts));
if (!edits) return nullptr; // <=
....
}
ãã®ã³ãŒãã¹ããããã¯ãã¡ã¢ãªãªãŒã¯ã®å€å žçãªäŸãå«ãŸããŠããŸãïŒèªã¿åã颿°åŒã³åºãããªã¿ãŒã³nullptråŒãã«å²ãåœãŠãããã¡ã¢ãªã®è§£æŸããã«ãæ°ããEditFstDataããã ïŒdelete dataãåŒã³åºããã«ïŒé¢æ°ããã®ããã«çµäºãããšããã€ã³ã¿ãŒèªäœã®ã¿ãåé€ããããã€ã³ã¿ãŒãæããªããžã§ã¯ãã®ãã¹ãã©ã¯ã¿ã¯åŒã³åºãããŸããããããã£ãŠããªããžã§ã¯ãã¯åŒãç¶ãã¡ã¢ãªã«ä¿åãããåé€ãŸãã¯äœ¿çšããããšã¯ã§ããªããªããŸãã
ãšã©ãŒã«å ããŠããã®ã³ãŒãã«ã¯ãããŸãè¯ããªãå¥ã®ãã©ã¯ãã£ã¹ãå«ãŸããŠããŸãã1ã€ã®é¢æ°ã®ã³ãŒãã¯ãã¹ããŒããã€ã³ã¿ãŒãšéåžžã®ãã€ã³ã¿ãŒã®äž¡æ¹ãåæã«äœ¿çšããŸããããšãã°ãããŒã¿ã®å Žåãã¹ããŒããã€ã³ã¿ã§ããã£ãå Žåããã®ãããªãšã©ãŒã¯çºçããŸãããå¿ èŠã«å¿ããŠãã¹ã³ãŒãå€ã«åºããšãã¹ããŒããã€ã³ã¿ã¯ä¿åããããªããžã§ã¯ãã®ãã¹ãã©ã¯ã¿ãèªåçã«åŒã³åºããŸãã
èŠå
2V1062ãDfsStateãã¯ã©ã¹ã¯ã«ã¹ã¿ã ã®ãnewãæŒç®åãå®çŸ©ããŸãã 'delete'æŒç®åãå®çŸ©ããå¿ èŠããããŸãã dfs-visit.h 62
// An FST state's DFS stack state.
template <class FST>
struct DfsState {
public:
....
void *operator new(size_t size,
MemoryPool<DfsState<FST>> *pool) {
return pool->Allocate();
}
....
}
PVS-Studioã¯åæ¢ãããæ°ãã蚺æã远å ãç¶ããŸãããã®ã³ãŒãã¹ããããã¯ãV1062ãšããçªå·ã®ææ°ã®èšºæã®äœæ¥ã瀺ãããã®åªããäŸã§ãã
ãã®èšºæãé©çšããã«ãŒã«ã¯åçŽã§ããç¬èªã®ãnewãæŒç®åãå®çŸ©ããå Žåã¯ãç¬èªã®ãdeleteãæŒç®åãå®çŸ©ããå¿ èŠããããŸããéãåãããã«æ©èœããŸããç¬èªã®ãåé€ããå®çŸ©ããå Žåã¯ãç¬èªã®ãæ°ããããå®çŸ©ããå¿ èŠããããŸãã
äžèšã®äŸã§ã¯ããã®ã«ãŒã«ã«éåããŠããŸãããªããžã§ã¯ãã¯ããŠãŒã¶ãŒãå®çŸ©ãããnewãã䜿çšããŠäœæãããæšæºã®ãdeleteãã䜿çšããŠåé€ãããŸããMemoryPoolã¯ã©ã¹ã®Allocate颿°ãäœããããèŠãŠã¿ãŸããããç§ãã¡èªèº«ã®ãæ°ããããåŒã¶ãã®ïŒ
void *Allocate() {
if (free_list_ == nullptr) {
auto *link = static_cast<Link *>(mem_arena_.Allocate(1));
link->next = nullptr;
return link;
} else {
auto *link = free_list_;
free_list_ = link->next;
return link;
}
}
ãã®é¢æ°ã¯ã¢ã€ãã ãäœæãããªã³ã¯ããããªã¹ãã«è¿œå ããŸãããã®ãããªå²ãåœãŠãããèªèº«ã®ãæ°ãããã§æžãããã¹ãã§ãã£ãããšã¯è«ççã§ãã
ããããã¡ãã£ãšåŸ ã£ãŠãã ããïŒä»¥äžã®æ°è¡ã«ã¯ã次ã®é¢æ°ãå«ãŸããŠããŸãã
void Free(void *ptr) {
if (ptr) {
auto *link = static_cast<Link *>(ptr);
link->next = free_list_;
free_list_ = link;
}
}
ããã¯ãå²ãåœãŠãšãªãªãŒã¹ã®äž¡æ¹ã®æ¢è£œã®æ©èœããã§ã«ããããšãæå³ããŸããã»ãšãã©ã®å Žåãããã°ã©ããŒã¯ãFreeïŒïŒé¢æ°ã䜿çšããŠãããè§£æŸããç¬èªã®ãåé€ãæŒç®åãäœæããå¿ èŠããããŸããã
ã¢ãã©ã€ã¶ãŒã¯ãå°ãªããšã3ã€ã®ãã®ãããªãšã©ãŒãæ€åºããŸããã
- V1062ãVectorStateãã¯ã©ã¹ã¯ã«ã¹ã¿ã ã®ãnewãæŒç®åãå®çŸ©ããŸãã'delete'æŒç®åãå®çŸ©ããå¿ èŠããããŸããvector-fst.h 31
- V1062'CacheState 'ã¯ã©ã¹ã¯ãã«ã¹ã¿ã ã®' new 'æŒç®åãå®çŸ©ããŸãã'delete'æŒç®åãå®çŸ©ããå¿ èŠããããŸããcache.h 65
èŠå
3V703掟çã¯ã©ã¹ãShortestPathOptionsãã®ãfirst_pathããã£ãŒã«ããåºæ¬ã¯ã©ã¹ãShortestDistanceOptionsãã®ãã£ãŒã«ããäžæžãããã®ã¯å¥åŠãªããšã§ãããã§ãã¯ã©ã€ã³ïŒshortest-path.hïŒ35ãshortest-distance.hïŒ34ãshortest-path.h 35
// Base class
template <class Arc, class Queue, class ArcFilter>
struct ShortestDistanceOptions {
Queue *state_queue; // Queue discipline used; owned by caller.
ArcFilter arc_filter; // Arc filter (e.g., limit to only epsilon graph).
StateId source; // If kNoStateId, use the FST's initial state.
float delta; // Determines the degree of convergence required
bool first_path; // For a semiring with the path property (o.w.
// undefined), compute the shortest-distances along
// along the first path to a final state found
// by the algorithm. That path is the shortest-path
// only if the FST has a unique final state (or all
// the final states have the same final weight), the
// queue discipline is shortest-first and all the
// weights in the FST are between One() and Zero()
// according to NaturalLess.
ShortestDistanceOptions(Queue *state_queue, ArcFilter arc_filter,
StateId source = kNoStateId,
float delta = kShortestDelta)
: state_queue(state_queue),
arc_filter(arc_filter),
source(source),
delta(delta),
first_path(false) {}
};
// Derived class
template <class Arc, class Queue, class ArcFilter>
struct ShortestPathOptions
: public ShortestDistanceOptions<Arc, Queue, ArcFilter> {
using StateId = typename Arc::StateId;
using Weight = typename Arc::Weight;
int32 nshortest; // Returns n-shortest paths.
bool unique; // Only returns paths with distinct input strings.
bool has_distance; // Distance vector already contains the
// shortest distance from the initial state.
bool first_path; // Single shortest path stops after finding the first
// path to a final state; that path is the shortest path
// only when:
// (1) using the ShortestFirstQueue with all the weights
// in the FST being between One() and Zero() according to
// NaturalLess or when
// (2) using the NaturalAStarQueue with an admissible
// and consistent estimate.
Weight weight_threshold; // Pruning weight threshold.
StateId state_threshold; // Pruning state threshold.
ShortestPathOptions(Queue *queue, ArcFilter filter, int32 nshortest = 1,
bool unique = false, bool has_distance = false,
float delta = kShortestDelta, bool first_path = false,
Weight weight_threshold = Weight::Zero(),
StateId state_threshold = kNoStateId)
: ShortestDistanceOptions<Arc, Queue, ArcFilter>(queue, filter,
kNoStateId, delta),
nshortest(nshortest),
unique(unique),
has_distance(has_distance),
first_path(first_path),
weight_threshold(std::move(weight_threshold)),
state_threshold(state_threshold) {}
};
åæããŸããæœåšçãªãšã©ãŒãèŠã€ããã®ã¯ããã»ã©ç°¡åã§ã¯ãããŸããããïŒ
åé¡ã¯ãåºæ¬ã¯ã©ã¹ãšæŽŸçã¯ã©ã¹ã®äž¡æ¹ã«åãååã®ãã£ãŒã«ããå«ãŸããŠãããšããäºå®ã«ãããŸãïŒfirst_pathãããã«ãããæŽŸçã¯ã©ã¹ã«ã¯ãåºæ¬ã¯ã©ã¹ã®ãã£ãŒã«ãããã®ååã§ãªãŒããŒã©ã€ãããç¬èªã®ç°ãªããã£ãŒã«ãããããŸãããã®ãããªééãã¯æ·±å»ãªæ··ä¹±ã«ã€ãªããå¯èœæ§ããããŸãã
ç§ãäœãæå³ããã®ããããããçè§£ããããã«ãç§ã¯ç§ãã¡ã®ããã¥ã¡ã³ãããçãåæäŸãæ€èšããããšãææ¡ããŸããæ¬¡ã®ã³ãŒãããããšããŸãããã
class U {
public:
int x;
};
class V : public U {
public:
int x; // <= V703 here
int z;
};
ããã§ãååxã¯æŽŸçã¯ã©ã¹å ã§ãªãŒããŒã©ã€ããããŸããããã§åé¡ã¯ã次ã®ã³ãŒãã¯ã©ã®ãããªå€ãåºåããã®ããšããããšã§ãã
int main() {
V vClass;
vClass.x = 1;
U *uClassPtr = &vClass;
std::cout << uClassPtr->x << std::endl;
....
}
æªå®çŸ©ã®å€ãåºåããããšæãããå Žåã¯ããã®éãã§ãããã®äŸã§ã¯ããŠãããã¯æŽŸçã¯ã©ã¹ã®ãã£ãŒã«ãã«æžã蟌ãŸããŸãããèªã¿åãã¯åºæ¬ã¯ã©ã¹ã®ãã£ãŒã«ãããè¡ãããåºåæã«ã¯ãŸã å®çŸ©ãããŠããŸããã
ã¯ã©ã¹éå±€ã§ååãéè€ããããšã¯æœåšçãªééãã§ãããåé¿ããå¿ èŠããããŸã:)
èŠå4
V1004 nullptrã«å¯ŸããŠæ€èšŒãããåŸããaiterããã€ã³ã¿ãŒãå®å šã«äœ¿çšãããŸããã§ããããã§ãã¯ã©ã€ã³ïŒ107ã119ãvisit.h 119
template <....>
void Visit(....)
{
....
// Deletes arc iterator if done.
auto *aiter = arc_iterator[state];
if ((aiter && aiter->Done()) || !visit) {
Destroy(aiter, &aiter_pool);
arc_iterator[state] = nullptr;
state_status[state] |= kArcIterDone;
}
// Dequeues state and marks black if done.
if (state_status[state] & kArcIterDone) {
queue->Dequeue();
visitor->FinishState(state);
state_status[state] = kBlackState;
continue;
}
const auto &arc = aiter->Value(); // <=
....
}
aiter ãã€ã³ã¿ãŒã¯ãnullptrããã§ãã¯ãããåŸã«äœ¿çšãããŸããã¢ãã©ã€ã¶ãŒã¯ããã€ã³ã¿ãŒãnullptrã«ã€ããŠãã§ãã¯ãããå Žåããã§ãã¯äžã«ãã®ãããªå€ãæã€ããšãã§ãããšä»®å®ããŸãã
ãã®å Žåãå®éã«ãŒãã«çããå Žåã«aiterãã©ããªãããèŠãŠã¿ãŸãããããŸãããã®ãã€ã³ã¿ã¯ ' ifïŒïŒaiter && aiter-> DoneïŒïŒïŒ||ïŒVisitïŒ 'ã¹ããŒãã¡ã³ãã§ãã§ãã¯ãããŸãããã®æ¡ä»¶ã¯falseã«ãªããã®å Žåããã®ãã©ã³ãã«ã¯å ¥ããŸããããããŠãå€å žçãªãšã©ãŒã®ãã¹ãŠã®åºæºã«åŸã£ãŠãnullãã€ã³ã¿ãéåç §ãããŸãã'aiter-> ValueïŒïŒ;'ããã®éåç §ã«ãããæªå®çŸ©ã®åäœãçºçããŸãã
èŠå5
次ã®äŸã«ã¯ãäžåºŠã«2ã€ã®ãšã©ãŒãå«ãŸããŠããŸãã
- V595 nullptrã«å¯ŸããŠæ€èšŒãããåã«ããistrmããã€ã³ã¿ãŒã䜿çšãããŸããããã§ãã¯è¡ïŒ60ã61ãmapped-file.cc 60
- V595 nullptrã«å¯ŸããŠæ€èšŒãããåã«ããistrmããã€ã³ã¿ãŒã䜿çšãããŸããããã§ãã¯è¡ïŒ39ã61ãmapped-file.cc 39
MappedFile *MappedFile::Map(std::istream *istrm, bool memorymap,
const string &source, size_t size) {
const auto spos = istrm->tellg(); // <=
....
istrm->seekg(pos + size, std::ios::beg); // <=
if (istrm) { // <=
VLOG(1) << "mmap'ed region of " << size
<< " at offset " << pos
<< " from " << source
<< " to addr " << map;
return mmf.release();
}
....
}
ããã§èŠã€ãã£ããšã©ãŒã¯ãåã®äŸã®ãšã©ãŒãããæç¢ºã§ããistrmãã€ã³ã¿ãŒã¯æåã«éåç §ããïŒ2åïŒããã®åŸã§ãŒããã§ãã¯ãšãšã©ãŒãã°ãç¶ããŸããããã¯æç¢ºã«ç€ºããŠããŸããnullãã€ã³ã¿ãistrmãšããŠãã®é¢æ°ã«å°éãããšããã°ãªãã§æªå®çŸ©ã®åäœïŒãŸãã¯ãããããããã°ã©ã ã®ã¯ã©ãã·ã¥ïŒãçºçããŸããé害...ãã®ãããªãã°ãèŠéããŠã¯ãªããŸããã

èŠå
6V730ã¯ã©ã¹ã®ãã¹ãŠã®ã¡ã³ããŒãã³ã³ã¹ãã©ã¯ã¿ãŒå ã§åæåãããããã§ã¯ãããŸãããæ€æ»ãæ€èšããŠãã ããïŒstones_written_ãersatz_progress.cc 14
ErsatzProgress::ErsatzProgress()
: current_(0)
, next_(std::numeric_limits<uint64_t>::max())
, complete_(next_)
, out_(NULL)
{}
ã¢ãã©ã€ã¶ãŒã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãErzatzProgressæ§é ã®ãã¹ãŠã®ãã£ãŒã«ããåæåããããã§ã¯ãªãããšãèŠåããŸãããã®ã³ã³ã¹ãã©ã¯ã¿ãŒããã®æ§é ã®ãã£ãŒã«ãã®ãªã¹ããšæ¯èŒããŠã¿ãŸãããã
class ErsatzProgress {
....
private:
void Milestone();
uint64_t current_, next_, complete_;
unsigned char stones_written_;
std::ostream *out_;
};
å®éãã³ã³ã¹ãã©ã¯ã¿ãŒãstones_written_ãé€ããã¹ãŠã®ãã£ãŒã«ããåæåããããšãããããŸãã
泚ïŒãã®äŸã¯ãšã©ãŒã§ã¯ãªãå¯èœæ§ããããŸããå®éã®ãšã©ãŒã¯ãåæåãããŠããªããã£ãŒã«ãã®å€ã䜿çšãããŠããå Žåã«ã®ã¿çºçããŸãã
ãã ããV730蚺æã¯ããããã®ãŠãŒã¹ã±ãŒã¹ãäºåã«ãããã°ããã®ã«åœ¹ç«ã¡ãŸããçµå±ã®ãšãããèªç¶ãªçåãçããŸããããã°ã©ããŒãã¯ã©ã¹ã®ãã¹ãŠã®ãã£ãŒã«ããå ·äœçã«åæåããããšã«ããå Žåããªã1ã€ã®ãã£ãŒã«ããå€ãªãã®ãŸãŸã«ããçç±ãããã®ã§ãããããstones_written_
ãã£ãŒã«ãã誀ã£ãŠåæåãããªãã£ããšããç§ã®æšæž¬ã¯ãæ°è¡äžã«å¥ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã衚瀺ããããšãã«ç¢ºèªãããŸããã
ErsatzProgress::ErsatzProgress(uint64_t complete,
std::ostream *to,
const std::string &message)
: current_(0)
, next_(complete / kWidth)
, complete_(complete)
, stones_written_(0)
, out_(to)
{
....
}
ããã§ãã¯ã©ã¹ã®ãã¹ãŠã®ãã£ãŒã«ããåæåãããŸããããã«ãããããã°ã©ããŒã¯å®éã«ãã¹ãŠã®ãã£ãŒã«ããåæåããããšãèšç»ããŸãããã誀ã£ãŠ1ã€ã®ããšãå¿ããŠããŸããŸããã
èŠå
7V780éããã·ãïŒéPDSïŒã¿ã€ãã®ãªããžã§ã¯ã 'ïŒparams'ã¯ãmemset颿°ã䜿çšããŠåæåã§ããŸããã binary_format.cc 261
/* Not the best numbering system,
but it grew this way for historical reasons
* and I want to preserve existing binary files. */
typedef enum
{
PROBING=0,
REST_PROBING=1,
TRIE=2,
QUANT_TRIE=3,
ARRAY_TRIE=4,
QUANT_ARRAY_TRIE=5
}
ModelType;
....
struct FixedWidthParameters {
unsigned char order;
float probing_multiplier;
// What type of model is this?
ModelType model_type;
// Does the end of the file
// have the actual strings in the vocabulary?
bool has_vocabulary;
unsigned int search_version;
};
....
// Parameters stored in the header of a binary file.
struct Parameters {
FixedWidthParameters fixed;
std::vector<uint64_t> counts;
};
....
void BinaryFormat::FinishFile(....)
{
....
// header and vocab share the same mmap.
Parameters params = Parameters();
memset(¶ms, 0, sizeof(Parameters)); // <=
....
}
ãã®èŠåãçè§£ããã«ã¯ããŸãPDSã¿ã€ããšã¯äœããçè§£ããããšããå§ãããŸãã PDSã¯ãåçŽãªããŒã¿æ§é ã§ããPassive DataStructureã®ç¥ã§ãã ãPDSãã®ä»£ããã«ãPODã-ããã¬ãŒã³ãªãŒã«ãããŒã¿ããšèšãããšããããŸããç°¡åã«èšããšïŒãã·ã¢ã®ãŠã£ãããã£ã¢ããåŒçšïŒãPDSã¿ã€ãã¯ãã¡ã¢ãªå ã®ãã£ãŒã«ãã®å Žæãå³å¯ã«å®çŸ©ãããŠããããŒã¿ã¿ã€ãã§ãããã¢ã¯ã»ã¹å¶éãèªåå¶åŸ¡ã¯å¿ èŠãããŸãããç°¡åã«èšãã°ãçµã¿èŸŒã¿åã®ã¿ã§æ§æãããããŒã¿åã§ãã
PODã¿ã€ãã®ç¹åŸŽã¯ããããã®ã¿ã€ãã®å€æ°ããããªããã£ãã¡ã¢ãªç®¡ç颿°ïŒmemsetãmemcpyãªã©ïŒã䜿çšããŠå€æŽããã³åŠçã§ããããšã§ãããã ããããã¯ãéPDSãã¿ã€ãã«ã€ããŠã¯èšããŸããããããã®å€ã®ãã®ãããªäœã¬ãã«ã®åŠçã¯ãé倧ãªãšã©ãŒã«ã€ãªããå¯èœæ§ããããŸããããšãã°ãã¡ã¢ãªãªãŒã¯ãåããªãœãŒã¹ã®ããã«ãã©ãã·ã¥ããŸãã¯æªå®çŸ©ã®åäœã
PVS-Studioã¯ãäžèšã®ã³ãŒãã«å¯ŸããŠèŠåãçºè¡ããŸãããã®æ¹æ³ã§Parametersã¿ã€ãã®æ§é ãåŠçããããšã¯ã§ããŸããããã®æ§é ã®å®çŸ©ãèŠããšã2çªç®ã®ã¡ã³ããŒã®ã¿ã€ããstd :: vectorã§ããããšãããããŸãã..ããã®ã¿ã€ãã¯ãèªåã¡ã¢ãªç®¡çãç©æ¥µçã«äœ¿çšããã³ã³ãã³ãããŒã¿ã«å ããŠã远å ã®ãµãŒãã¹å€æ°ãæ ŒçŽããŸããmemsetã䜿çšããŠãã®ãããªãã£ãŒã«ãããŒãã«ãããšãã¯ã©ã¹ã®ããžãã¯ãç Žæããå¯èœæ§ããããé倧ãªééãã§ãã
èŠå
8V575æœåšçãªnullãã€ã³ã¿ããmemcpyã颿°ã«æž¡ãããŸããæåã®åŒæ°ã調ã¹ãŸãããã§ãã¯ã©ã€ã³ïŒ73ã68.modelstate.cc 73
Metadata*
ModelState::decode_metadata(const DecoderState& state,
size_t num_results)
{
....
Metadata* ret = (Metadata*)malloc(sizeof(Metadata));
....
memcpy(ret, &metadata, sizeof(Metadata));
return ret;
}
次ã®èŠåã¯ããã«ãã€ã³ã¿ãmemcpy颿°ã«æž¡ãããŠããããšã瀺ããŠããŸããã¯ãã確ãã«ãmalloc颿°ãã¡ã¢ãªã®å²ãåœãŠã«å€±æããå ŽåãNULLãè¿ããŸãããã®å Žåããã®ãã€ã³ã¿ãŒã¯memset颿°ã«æž¡ãããããã§éåç §ãããŸãããããã£ãŠãé åçãªããã°ã©ã ãã¯ã©ãã·ã¥ããŸãã
ãã ããäžéšã®èªè ã¯æ€æ šããŠããå¯èœæ§ããããŸããã¡ã¢ãªããªãŒããŒãããŒ/æçåãããŠãmallocãã¡ã¢ãªãå²ãåœãŠãããšãã§ããªãã£ãå Žåãæ¬¡ã«äœãèµ·ãããã¯æ¬åœã«éèŠã§ããïŒã¡ã¢ãªäžè¶³ã®ããã«ããã°ã©ã ãæ£åžžã«æ©èœã§ããªããªããããããã°ã©ã ã¯ãšã«ããã¯ã©ãã·ã¥ããŸãã
ç§ãã¡ã¯ãã®æèŠã«ç¹°ãè¿ãåºããããããã¯ééã£ãŠãããšä¿¡ããŠããŸãããªããããªã®ãã詳ããã話ãããŸããããã®ãããã¯ã¯å¥ã®èšäºã«å€ããŸããæ°å¹Žåã«æžããã®ã¯éåžžã«äŸ¡å€ããããŸã:)ãªãmalloc颿°ã«ãã£ãŠè¿ããããã€ã³ã¿ãåžžã«ãã§ãã¯ããå¿ èŠãããã®ãââçåã«æã£ãŠããå Žåã¯ãèªãã§ãã ããïŒmallocãäœãè¿ãããããã§ãã¯ããããšãéèŠãªã®ã¯ãªãã§ããã
èŠå9
次ã®èŠåã¯ãåã®èŠåãšåãçç±ã§çºçããŸãã確ãã«ãããã¯ãããã«ç°ãªããšã©ãŒã瀺ããŠããŸãã
V769'middle_begin_ +ïŒcounts.sizeïŒïŒ-2ïŒ'åŒã® 'middle_begin_'ãã€ã³ã¿ãŒã¯nullptrã§ããå¯èœæ§ããããŸãããã®ãããªå Žåãçµæã®å€ã¯ç¡æå³ã«ãªãããã䜿çšããªãã§ãã ããããã§ãã¯ã©ã€ã³ïŒ553ã552ãsearch_trie.cc 553
template <class Quant, class Bhiksha> class TrieSearch {
....
private:
....
Middle *middle_begin_, *middle_end_;
....
};
template <class Quant, class Bhiksha>
uint8_t *TrieSearch<Quant, Bhiksha>::SetupMemory(....)
{
....
middle_begin_
= static_cast<Middle*>(malloc(sizeof(Middle) * (counts.size() - 2)));
middle_end_ = middle_begin_ + (counts.size() - 2);
....
}
åã®äŸãšåæ§ã«ãããã§ã¯malloc颿°ã䜿çšããŠã¡ã¢ãªãå²ãåœãŠãããŸããnullptrããã§ãã¯ããã«è¿ããããã€ã³ã¿ã¯ãç®è¡åŒã§äœ¿çšãããŸããæ®å¿µãªããããã®ãããªåŒã®çµæã¯æå³ããªãããå®å šã«åœ¹ã«ç«ããªãå€ãmiddle_end_ãã£ãŒã«ãã«æ ŒçŽãããŸãã
èŠå10
ãããŠæåŸã«ãç§ã®æèŠã§æãè峿·±ãäŸã¯ãDeepSpeechã«å«ãŸããŠããkenlmã©ã€ãã©ãªã«ãããŸãããV1061 ãstdãåå
åãæ¡åŒµãããšãæªå®çŸ©ã®åäœãçºçããå¯èœæ§ããããŸãã sized_iterator.hh 210
// Dirty hack because g++ 4.6 at least wants
// to do a bunch of copy operations.
namespace std {
inline void iter_swap(util::SizedIterator first,
util::SizedIterator second)
{
util::swap(*first, *second);
}
} // namespace std
ã³ã¡ã³ãã§ãããŒãã£ããªãã¯ããšåŒã°ããããªãã¯ã¯æ¬åœã«ããŒãã£ã§ããéèŠãªã®ã¯ãstdåå空éã®ãã®ãããªæ¡åŒµã¯ãæªå®çŸ©ã®åäœã«ã€ãªããå¯èœæ§ããããšããããšã§ãã
ã©ãããŠïŒstdåå空éã®å 容ã¯ãæšæºå§å¡äŒã«ãã£ãŠç¬å çã«æ±ºå®ãããããã§ãããã®ãããC ++èšèªã®åœéæšæºã§ã¯ããã®æ¹æ³ã§stdãæ¡åŒµããããšãæç€ºçã«çŠæ¢ããŠããŸãã
g ++ 4.6ã§ãµããŒããããæåŸã®æšæºã¯C ++ 03ã§ããããã¯ãC ++ 03æçµäœæ¥ãã©ããããã®ç¿»èš³ãããåŒçšã§ããïŒé ç®17.6.4.2.1ãåç §ïŒïŒãç¹ã«æå®ããªãéããC ++ããã°ã©ã ãstdåå空éãŸãã¯stdãã¹ããããåå空éã«å®£èšãŸãã¯å®çŸ©ã远å ããå ŽåãC ++ããã°ã©ã ã®åäœã¯æªå®çŸ©ã§ããããã®èŠç©ããã¯ãåŸç¶ã®ãã¹ãŠã®æšæºïŒC ++ 11ãC ++ 14ãC ++ 17ãããã³C ++ 20ïŒã«é©çšãããŸãã
ãã®äŸããåé¡ã®ããã³ãŒããä¿®æ£ããæ¹æ³ãæ€èšããããšãææ¡ããŸããæåã®è«ççãªè³ªåïŒãããã®ãå察ã瀺ãããŠããã±ãŒã¹ããšã¯äœã§ããïŒstdå±éãæªå®çŸ©ã®åäœãåŒãèµ·ãããªãç¶æ³ãããã€ããããŸããããããã¹ãŠã®ç¶æ³ã®è©³çްã«ã€ããŠã¯ãV1061蚺æã®ããã¥ã¡ã³ãããŒãžãåç §ããŠãã ããããã ãããããã®ã±ãŒã¹ã®1ã€ãã颿°ãã³ãã¬ãŒãã®ç¹æ®åã®è¿œå ã§ããããšãéèŠã§ãã
ãªããªãstdã«ã¯ãã§ã«iter_swapïŒæ³šïŒãã³ãã¬ãŒã颿°ïŒãšåŒã°ãã颿°ããããŸããããã°ã©ããŒãutil :: SizedIteratorã¿ã€ãã§åäœã§ããããã«ããã®æ©èœãæ¡åŒµããããšèããã®ã¯è«ççã§ããããããããã«äžéããããŸãã颿°ãã³ãã¬ãŒãã«ç¹æ®åã远å ãã代ããã«ãããã°ã©ããŒã¯åã«éåžžã®ãªãŒããŒããŒããäœæããŸãããæ¬¡ã®ããã«æžãå¿ èŠããããŸãã
namespace std {
template <>
inline void iter_swap(util::SizedIterator first,
util::SizedIterator second)
{
util::swap(*first, *second);
}
} // namespace std
ãã ãããã®ã³ãŒããããã»ã©åçŽã§ã¯ãããŸãããéèŠãªã®ã¯ããã®ã³ãŒãã¯C ++ 20æšæºãŸã§ããæå¹ã§ã¯ãªããšããããšã§ããã¯ãããŸãã颿°ãã³ãã¬ãŒãã®ç¹æ®åãæªå®çŸ©ã®åäœã«ã€ãªããããšã«ãèšåããŸããïŒC ++ 20æçµäœæ¥ãã©ããã®ã»ã¯ã·ã§ã³16.5.4.2.1ãåç §ïŒããŸãããã®ã³ãŒãã¯ã©ã€ãã©ãªã«å±ããŠãããããé ããæ©ãã-std = C ++ 20ãã©ã°ã䜿çšããŠãã«ããããå¯èœæ§ããããŸããã¡ãªã¿ã«ãPVS-Studioã¯ãã³ãŒãã§äœ¿çšãããŠããæšæºã®ããŒãžã§ã³ãåºå¥ããããã«å¿ããŠãèŠåãçºè¡ãããã©ãããæ±ºå®ããŸããèªåèªèº«ãåç §ããŠãã ããïŒC ++ 17ããšãã°ãC ++ 20ã®ããã®äžäŸã
å®éãã¯ããã«ç°¡åã«è¡ãããšãã§ããŸãããšã©ãŒãä¿®æ£ããã«ã¯ãiter_swapã®ç¬èªã®å®çŸ©ã転éããå¿ èŠããããŸãSizedIteratorã¯ã©ã¹ãå®çŸ©ããåãåååã«ããã®å Žåãiter_swapãåŒã³åºãããå Žæã«ããusing std :: iter_swap;ãã远å ããå¿ èŠããããŸããããã¯æ¬¡ã®ããã«ãªããŸãïŒSizedIteratorã¯ã©ã¹ãšutil :: swapïŒïŒé¢æ°ã®å®çŸ©ã¯ç°¡åã«ããããã«å€æŽãããŠããŸãïŒïŒ
namespace util
{
class SizedIterator
{
public:
SizedIterator(int i) : m_data(i) {}
int& operator*()
{
return m_data;
}
private:
int m_data;
};
....
inline void iter_swap(SizedIterator first,
SizedIterator second)
{
std::cout << "we are inside util::iter_swap" << std::endl;
swap(*first, *second);
}
}
int main()
{
double d1 = 1.1, d2 = 2.2;
double *pd1 = &d1, *pd2 = &d2;
util::SizedIterator si1(42), si2(43);
using std::iter_swap;
iter_swap(pd1, pd2);
iter_swap(si1, si2); // "we are inside util::iter_swap"
return 0;
}
ããã§ãã³ã³ãã€ã©ã¯ãåŒæ°æ€çŽ¢ïŒADLïŒã«åºã¥ããŠãiter_swap颿°ã®å¿ èŠãªãªãŒããŒããŒããåå¥ã«éžæããŸããSizedIteratorã¯ã©ã¹ã®å Žåãnamespace utilã®ããŒãžã§ã³ãåŒã³åºãããä»ã®ã¿ã€ãã®å Žåãnamespacestdã®ããŒãžã§ã³ãåŒã³åºãããŸãã蚌æ ã¯ãªã³ã¯ã«ãããŸããããã«ãã©ã€ãã©ãªé¢æ°å ã«ãusingãã远å ããå¿ èŠã¯ãããŸãããã³ãŒãã¯ãã§ã«stdå ã«ãããããã³ã³ãã€ã©ã¯æ£ãããªãŒããŒããŒããéžæããŸãã
ãããŠ-åºæ¥äžãã-ã«ã¹ã¿ã iter_swap颿°ã¯ããæ±ãããªãã¯ãããã®ä»ã®éè¡ããªããŠãæ£åžžã«æ©èœããŸã:)

çµè«
ããã§ç§ã®èšäºã¯çµããã§ããç§ãèŠã€ãããšã©ãŒãããªãã«ãšã£ãŠè峿·±ããã®ã§ãããããªããããªãèªèº«ã«ãšã£ãŠæ°ãããŠåœ¹ã«ç«ã€äœããåŠãã ããšãé¡ã£ãŠããŸãããããŸã§èªãã ããšããããªãããšã©ãŒã®ãªãã¯ãªãŒã³ã§æŽé ãããã³ãŒããå¿ããé¡ã£ãŠããŸãããã°ããããžã§ã¯ãããã€ãã¹ããããã«ããŸãããïŒ
PSåååstdã«ç¬èªã®ã³ãŒããæžãã®ã¯æªãç¿æ £ã ãšæããŸããã©ãæããŸããïŒã³ã¡ã³ãã§ã®ãåçããåŸ ã¡ããŠãããŸãã
CãC ++ãCïŒããŸãã¯Javaã§éçºããŠããŠãç§ã®ããã«éçåæã®ãããã¯ã«èå³ãããå Žåã¯ãPVS-Studioãèªåã§è©Šãããšããå§ãããŸãããªã³ã¯ããããŠã³ããŒãã§ããŸãã

ãã®èšäºãè±èªã話ãèŽè¡ãšå ±æãããå Žåã¯ã翻蚳ãªã³ã¯ã䜿çšããŠãã ããïŒGeorgeGribkovãDeepSpeechã®ã³ãŒãã確èªããããŸãã¯åååstdã«æžã蟌ãã¹ãã§ã¯ãªãçç±ã
